Alert dialog
Un 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.
pnpm dlx shadcn@latest add https://hextaui.com/r/alert-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/alert-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.
Acción asíncrona
Devuelve una promesa desde el onClick de <AlertDialogAction />. El botón muestra un spinner y el diálogo no se puede cerrar hasta que la promesa se resuelva. Se cierra cuando se cumple y permanece abierto cuando se rechaza, para que se pueda reintentar.
Media
<AlertDialogMedia /> coloca un icono junto al título en escritorio y encima en teléfonos. Usa variant="destructive" para acciones destructivas.
Pequeño
size="sm" centra el contenido y coloca los botones uno al lado del otro, para preguntas cortas.
Triggers desacoplados
Crea un handle con createAlertDialogHandle() para compartir un diálogo entre muchos triggers. Cada trigger pasa su propio payload, que el diálogo lee mediante una función de renderizado.
Controlado
Pasa open y onOpenChange para abrirlo desde código, sin un trigger. El foco sigue yendo a Cancel.
Anidado
Un diálogo abierto desde dentro de otro se apila encima. El principal se reduce mientras el hijo está abierto y vuelve al frente cuando este se cierra.
Contenido largo
El contenido más alto que la pantalla se desplaza dentro del diálogo mientras la página permanece bloqueada.
De derecha a izquierda
Pasa también dir al contenido, porque se renderiza en un portal fuera de tu contenedor RTL. Las teclas de flecha en el pie siguen la dirección de lectura.
| Key | Acción |
|---|---|
| EnterSpace | En el trigger, abre el diálogo y mueve el foco a Cancel. |
| TabShift+Tab | Mueve el foco entre los controles. El foco permanece dentro. |
| ←→↑↓ | Se mueve entre los botones del pie y da la vuelta al llegar al final. Izquierda y derecha siguen la dirección de lectura. |
| Esc | Cierra el diálogo y devuelve el foco al trigger. Se ignora mientras una acción asíncrona está en curso. |
- El contenido tiene
role="alertdialog", está etiquetado por su título y descrito por su descripción. - El foco empieza en
<AlertDialogCancel />, la opción menos destructiva. PasainitialFocuspara cambiarlo. - Hacer clic en el fondo no lo cierra, así que una decisión nunca se descarta por accidente. Define
disablePointerDismissal={false}para permitirlo. - En teléfonos se convierte en una hoja inferior que se puede deslizar hacia abajo para cancelar. Mientras una acción está pendiente, deslizar, Esc y Cancel quedan bloqueados y los botones siguen pudiendo recibir foco.
- Con movimiento reducido, se desvanece en lugar de escalar.
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 |
onOpenChangeNo se llama en los cierres bloqueados por una acción pendiente. | (open: boolean, details) => void | – |
onOpenChangeCompleteSe llama después de la animación de apertura o cierre. | (open: boolean) => void | – |
disablePointerDismissalMantiene el diálogo abierto al hacer clic en el fondo. | boolean | true |
handleConecta triggers desacoplados. | AlertDialogHandle<Payload> | – |
actionsRefCierra o desmonta el diálogo de forma imperativa. | RefObject<{ close, unmount }> | – |
children | ReactNode | ({ payload }) => ReactNode | – |
| Prop | Tipo | Predeterminado |
|---|---|---|
handle | AlertDialogHandle<Payload> | – |
payloadSe pasa a la función de renderizado del diálogo. | Payload | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-trigger" | Apunta a los triggers en CSS. |
data-popup-open | Presente mientras su diálogo está abierto. |
| Prop | Tipo | Predeterminado |
|---|---|---|
size | "default" | "sm" | "default" |
initialFocus | boolean | RefObject | (openType) => HTMLElement | boolean | Cancel button |
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="alert-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 elemento multimedia, el título y la descripción.
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-header" | Apunta al encabezado en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
variant | "default" | "destructive" | "default" |
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-media" | Selecciona el elemento multimedia en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <h2> |
| Atributo | Descripción |
|---|---|
data-slot="alert-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="alert-dialog-description" | Apunta a la descripción en CSS. |
Un <div> para los botones. Los botones se apilan a todo el ancho en teléfonos, y las teclas de flecha se mueven entre ellos.
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-footer" | Selecciona el pie en CSS. |
Un <Button /> que cierra el diálogo al hacer clic. Acepta todas las props de Button.
| Prop | Tipo | Predeterminado |
|---|---|---|
onClickDevuelve una promesa para mostrar un spinner y mantener el diálogo abierto hasta que se resuelva. Llama a event.preventDefault() para mantenerlo abierto. | (event) => void | PromiseLike<unknown> | – |
variant | ButtonVariant | "default" |
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-action" | Selecciona las acciones en CSS. |
| Prop | Tipo | Predeterminado |
|---|---|---|
variant | ButtonVariant | "outline" |
size | ButtonSize | – |
disabledTambién se deshabilita mientras una acción está pendiente. | boolean | – |
| Atributo | Descripción |
|---|---|
data-slot="alert-dialog-cancel" | Selecciona el botón de cancelar en CSS. Recibe el foco inicial. |
data-disabled | Presente mientras está deshabilitado. |
<AlertDialogContent /> 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 <AlertDialogTrigger /> de cualquier parte de la página con un único <AlertDialog />. Tipa el payload con un genérico: createAlertDialogHandle<{ 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.
- 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.
- DialogUna ventana sobre la página para formularios y tareas concretas, con encabezado y pie fijados, anidamiento y una hoja inferior deslizable en móviles.
- 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 Alert dialog.
- 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.
- NotificationsLa sección Notificaciones de los ajustes de un producto de IA. Una cuadrícula de canal por evento con toggles por fila, por columna y para todo, horas de silencio con una línea en vivo del próximo silencio, un resumen por correo, envíos de prueba reales para escritorio, correo, push y Slack, gestión de permisos del navegador y un flujo para conectar Slack. Se integra en cualquier sección de Ajustes.
- SecuritySesiones y seguridad para un producto de IA. Dispositivos activos con cierre de sesión que anima la salida de las filas, cambio de contraseña con un medidor de fortaleza en vivo, configuración de dos factores con un código QR real, una verificación de 6 dígitos y códigos de recuperación descargables, passkeys mediante WebAuthn y eliminación de la cuenta tras una confirmación escrita.