Modal
Modal accesible basado en Radix Dialog. Cierra con Escape y click fuera. Compound component: Modal.Footer para las acciones.
pnpm dlx nuvo-ui add modalConfirmación — uso más común
const [open, setOpen] = React.useState(false)
<Button variant="destructive" onClick={() => setOpen(true)}>
Eliminar usuario
</Button>
<Modal
open={open}
onOpenChange={setOpen}
title="Confirmar eliminación"
description="Esta acción no se puede deshacer."
>
<Modal.Footer>
<Button variant="outline" onClick={() => setOpen(false)}>Cancelar</Button>
<Button variant="destructive" onClick={handleDelete}>Eliminar</Button>
</Modal.Footer>
</Modal>Con formulario
<Modal open={open} onOpenChange={setOpen} title="Nuevo usuario">
<div className="space-y-4">
<Input label="Nombre" placeholder="Ana" />
<Input label="Email" type="email" placeholder="ana@empresa.com" />
</div>
<Modal.Footer>
<Button variant="outline" onClick={() => setOpen(false)}>Cancelar</Button>
<Button onClick={handleSubmit}>Enviar invitación</Button>
</Modal.Footer>
</Modal>Nota: El modal usa
focus trap automático — el foco queda atrapado dentro mientras está abierto y vuelve al elemento disparador al cerrarse.Props
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| open | boolean | — | Controla si el modal está abierto |
| onOpenChange | (open: boolean) => void | — | Callback al cambiar estado |
| title | string | — | Título del modal (Radix Dialog.Title) |
| description | string | — | Descripción (Radix Dialog.Description) |
| maxWidth | "sm" | "md" | "lg" | "xl" | "md" | Ancho máximo del panel |
| children | ReactNode | — | Contenido del modal |