Dialog
Una ventana sobre la página para formularios y tareas concretas, con encabezado y pie fijados, anidamiento y una hoja inferior deslizable en móviles.
pnpm dlx shadcn@latest add https://hextaui.com/r/dialog.jsonAñade el componente, los tokens del tema de HextaUI y los componentes de HextaUI de los que depende.
Añade los tokens del tema a tu CSS global, si aún no lo has hecho.
Instala las dependencias.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopia y pega el siguiente código en tu proyecto.
components/ui/dialog.tsx components/ui/sheet.tsx components/ui/button.tsx Actualiza las rutas de importación para que coincidan con la configuración de tu proyecto.
Form
Mantén el formulario en <DialogBody /> y apunta el botón de envío del pie a él con form. Enter envía, y el diálogo se cierra mediante onOpenChange una vez guardado el valor.
Botón de cierre personalizado
Oculta el botón de la esquina con showCloseButton={false} en el contenido y añade un botón Close al pie con showCloseButton.
Sin botón de cierre
Sin botón, el diálogo sigue cerrándose con Esc, un clic fuera o un deslizamiento hacia abajo en teléfonos.
Tamaños
size define el ancho máximo en pantallas más grandes: sm, default o lg.
Pie fijo
El contenido largo en <DialogBody /> se desplaza mientras el encabezado y el pie permanecen en su sitio, así que las acciones siempre están al alcance.
Contenido desplazable
Sin pie, el cuerpo se desplaza bajo el encabezado y conserva su relleno inferior.
Controlado
Pasa open y onOpenChange para abrirlo desde código, sin un trigger.
Anidado
Un dialog o alert dialog abierto desde dentro de otro se apila encima. El padre retrocede y un fondo más claro lo cubre. Esc cierra solo el de arriba.
Triggers desacoplados
Crea un handle con createDialogHandle() para compartir un diálogo entre muchos triggers. Cada trigger pasa un payload que el diálogo lee mediante una función de renderizado.
De derecha a izquierda
Pasa también dir al contenido, porque se renderiza en un portal fuera de tu contenedor RTL.
| Key | Acción |
|---|---|
| EnterSpace | En el trigger, abre el diálogo y mueve el foco a su primer control. |
| TabShift+Tab | Mueve el foco entre los controles. El foco permanece dentro. |
| Esc | Cierra el diálogo superior y devuelve el foco a su trigger. |
- El contenido tiene
role="dialog", está etiquetado por su título y descrito por su descripción. Incluye siempre un<DialogTitle />. - Con ratón o teclado, el foco empieza en el primer control. Con táctil empieza en el propio diálogo, para que el teclado en pantalla no cubra el contenido antes de que se elija un campo. Pasa
initialFocuspara cambiarlo. - El botón de cierre de la esquina tiene la etiqueta “Close”, y la página de detrás es inerte y no se puede desplazar.
- En teléfonos se convierte en una hoja inferior que se puede deslizar hacia abajo para cerrar. Con movimiento reducido, se desvanece en lugar de escalar o deslizarse.
Construido sobre el drawer de Base UI, mediante <Sheet />. Cada parte acepta las props de la primitiva o el elemento que envuelve.
| Prop | Tipo | Predeterminado |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChange | (open: boolean, details) => void | – |
onOpenChangeCompleteSe llama después de la animación de apertura o cierre. | (open: boolean) => void | – |
modal | boolean | "trap-focus" | true |
disablePointerDismissalMantiene el diálogo abierto al hacer clic fuera. | boolean | false |
handleConecta triggers desacoplados. | DialogHandle<Payload> | – |
actionsRefCierra o desmonta el diálogo de forma imperativa. | RefObject<{ close, unmount }> | – |
children | ReactNode | ({ payload }) => ReactNode | – |
| Prop | Tipo | Predeterminado |
|---|---|---|
handle | DialogHandle<Payload> | – |
payloadSe pasa a la función de renderizado del diálogo. | Payload | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descripción |
|---|---|
data-slot="dialog-trigger" | Apunta a los triggers en CSS. |
data-popup-open | Presente mientras su diálogo está abierto. |
| Prop | Tipo | Predeterminado |
|---|---|---|
size | "sm" | "default" | "lg" | "default" |
showCloseButtonMuestra el botón de cierre en la esquina. | boolean | true |
initialFocus | boolean | RefObject | (openType) => HTMLElement | boolean | First control, or the dialog on touch |
finalFocus | boolean | RefObject | (closeType) => HTMLElement | boolean | The trigger |
dirDefínelo cuando el diálogo deba ir de derecha a izquierda. | "ltr" | "rtl" | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Atributo | Descripción |
|---|---|
data-slot="dialog-content" | Selecciona el diálogo en CSS. |
data-size | El tamaño actual. |
data-open | Presente mientras está abierto. |
data-starting-style | Presente mientras el diálogo se anima al abrirse. |
data-ending-style | Presente mientras el diálogo se anima al cerrarse. |
data-nested-drawer-open | Presente mientras un diálogo anidado está abierto encima. |
data-swiping | Presente mientras se desliza en un teléfono. |
--nested-drawers | Cuántos diálogos están abiertos encima de este. |
Un <div> que apila el título y la descripción. Deja espacio para el botón de cierre.
| Atributo | Descripción |
|---|---|
data-slot="dialog-header" | Apunta al encabezado en CSS. |
Un <div> que se desplaza cuando el contenido es más alto que la pantalla, manteniendo el encabezado y el pie en su sitio.
| Atributo | Descripción |
|---|---|
data-slot="dialog-body" | Selecciona el cuerpo en CSS. |
Un <div> para las acciones. Los botones se apilan a todo el ancho en teléfonos, con el primero abajo.
| Prop | Tipo | Predeterminado |
|---|---|---|
showCloseButtonAñade un botón Close outline después de los hijos. | boolean | false |
| Atributo | Descripción |
|---|---|
data-slot="dialog-footer" | Selecciona el pie en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <h2> |
| Atributo | Descripción |
|---|---|
data-slot="dialog-title" | Apunta al título en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
renderUsa render={<div />} cuando contenga varios párrafos. | ReactElement | (props, state) => ReactElement | <p> |
| Atributo | Descripción |
|---|---|
data-slot="dialog-description" | Apunta a la descripción en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descripción |
|---|---|
data-slot="dialog-close" | Selecciona los botones de cierre en CSS. |
<DialogContent /> ya renderiza ambos. Úsalos solo al componer un popup personalizado.
| Prop | Tipo | Predeterminado |
|---|---|---|
keepMountedEn el portal, mantiene el diálogo en el DOM mientras está cerrado. | boolean | false |
Devuelve un handle que conecta elementos <DialogTrigger /> de cualquier parte de la página con un único <Dialog />. Tipa el payload con un genérico: createDialogHandle<{ name: string }>().
- ButtonBotones en todas las variantes y tamaños, con un flujo integrado de carga, éxito y error que omite el spinner en las peticiones rápidas.
- SheetUn panel que se desliza desde cualquier borde, con deslizamiento para descartar, bloqueo de scroll y anidamiento apilado.
- Alert dialogUn diálogo de confirmación para acciones destructivas o importantes que espera el trabajo asíncrono y se convierte en una hoja inferior en móviles.
- CommandUna lista de acciones con búsqueda, en línea o como paleta ⌘K, con páginas, atajos y coincidencias resaltadas.
- Context menuUn menú de acciones con clic derecho o pulsación larga, con submenús, elementos de casilla y de radio, y respuesta al mantener pulsado en pantallas táctiles.
- DrawerUn panel que se desliza desde cualquier borde y sigue tu dedo, con puntos de anclaje, un tirador funcional y drawers anidados que se apilan.
Usado en bloques
Bloques que se construyen sobre Dialog.
- Prompt InputUn compositor de chat que empieza como una línea tranquila, crece hasta convertirse en una tarjeta mientras escribes y baja cuando empieza la conversación. Enter envía, de forma segura con entrada en japonés y chino. Pega, suelta o elige archivos con vistas previas, progreso y reintento. @ añade archivos y / ejecuta comandos desde un menú junto al cursor. Un selector de modelo con teclas numéricas, un control deslizante de esfuerzo que cobra vida en Max, un anillo de contexto, dictado con forma de onda en vivo, chips de herramientas, una cola para los mensajes escritos mientras se transmite una respuesta y borradores que sobreviven a una recarga.
- API keysLa página de claves de API de un producto de IA, como las consolas de OpenAI y Anthropic. Crea claves con permisos acotados y caducidad, ve el secreto una sola vez con una copia que lo confirma, revoca con deshacer, renombra en el sitio, rota con un periodo de gracia y consulta el uso por clave.
- BillingPlan y uso para un producto de IA, al estilo de Cursor, Claude y Vercel. Un medidor de uso dividido por modelo que proyecta el final del ciclo y avisa antes de que se agoten los créditos, un gráfico diario por el que puedes desplazarte, un límite de gasto con alertas que puedes previsualizar en el medidor, cambios de plan con prorrateo exacto, un formulario de tarjeta con validación real y facturas descargables en PDF.
- ModelsLa página Modelos de los ajustes de un producto de IA. Un modelo predeterminado con su contexto, velocidad y coste de un vistazo, un esfuerzo predeterminado que sabe qué admite cada modelo, una lista de modelos con búsqueda agrupada por proveedor con filtros, fijados e interruptores masivos, servidores compatibles con OpenAI con una prueba de conexión real y una actualización que te dice qué hay de nuevo.