Saltar al contenido
EspañolEnglish
Todos los componentes (204)

Diálogo

Capas · Dialog · .amset-dialog

Qué es y cuándo usarlo

Un diálogo modal: corta el paso hasta que se contesta. Es un <dialog> nativo abierto con showModal(): lleva el foco dentro al abrir, lo mantiene ahí mientras está abierto, deja inerte el resto de la página y lo devuelve al disparador al cerrar.

Cuándo usarlo

  • Una decisión que no se puede ignorar, o un formulario corto que tiene sentido sin salir de la pantalla.
  • kind="alert" para confirmaciones destructivas: se anuncia como alertdialog y no se cierra pulsando fuera, para que un clic perdido no conteste por nadie. Escape sí la cierra, como cancelación (el patrón alertdialog de WAI-ARIA).
  • Con trigger se abre y se cierra solo; sin él, lo lleva quien lo usa con open y onOpenChange.
  • actions recibe close, así el botón de la acción cierra sin llevar el estado fuera; footerStart pone algo a la izquierda del pie.
  • loading mientras llega lo de dentro: el cuerpo lleva aria-busy y dice loadingText («Cargando…»).
  • dismissable={false} para un formulario a medias que no debe perderse por un clic fuera.

Cuándo no

  • Un «¿seguro?» pegado al botón: ConfirmAction. Si se pregunta desde código, useConfirmation.
  • Filtros o el detalle de una fila, que entran por un lado: Drawer.
  • Un panel pegado a su botón, sin velo: Dropdown.
  • Si necesita desplazarse mucho, probablemente sea una página.

Teclado: al abrir, el foco entra; Tab y Mayús+Tab se quedan dentro. Escape cierra y el foco vuelve al disparador; en kind="alert" cuenta como cancelar y llega a onOpenChange(false). Pulsar fuera cierra solo el normal.

Accesibilidad: se anuncia como dialog (o alertdialog) con el título como nombre, y description como descripción accesible. El aspa sale con withCloseButton, nunca en los de alerta, y se llama con closeLabel («Cerrar el diálogo»). El icono del tone es adorno: el título tiene que decirlo todo. onClosed llega cuando el diálogo ya se ha ido (tras la animación de salida) y el foco ya ha vuelto: es el sitio para mover el foco a otra parte o anunciar algo.

Aspecto fino: variables CSS --amset-dialog-*: -width, -padding, -radius, -background y -slot; el velo, --amset-overlay-background y --amset-overlay-padding. Lo que se apila sale de la escalera --amset-layer-* (lo modal es la 100).

Cabecera propia: icon (con el color de accent) en lugar del del tono, headerActions entre el título y el aspa, y title puede ser un nodo. width da un ancho propio (un número son píxeles, un texto es una medida CSS) y manda sobre size; placement="top" lo pega arriba, para lo que crece hacia abajo como una paleta; hideHeader esconde la cabecera sin perder el nombre accesible; flush quita el relleno del cuerpo y bodyColumn lo hace columna flex, para contenido con su propio desplazamiento.

Incrustado: con inline la misma caja se pinta EN la página, como una región con su título: sin <dialog>, sin fondo, sin Escape ni trampa de foco y sin aspa. Sirve para reutilizar como panel de una pantalla lo que en otra es un diálogo. open la muestra o la esconde.

Lo que se desplaza es el cuerpo: la cabecera y el pie se quedan quietos, y las rayas que los separan solo aparecen si el cuerpo no cabe entero. Con el diálogo entero desplazándose, en uno largo el título se iba de la pantalla (medido: −563 px tras desplazar 600) y los botones solo salían al llegar al final.

Cómo se ve

<Dialog
  title="Eliminar el pedido"
  description="Esto no se puede deshacer."
  trigger={<Button variant="soft" tone="error">Eliminar</Button>}
  actions={(cerrar) => <Button variant="solid" tone="error" onClick={cerrar}>Si, eliminar</Button>}
>
  <Text>Se perdera el historial de envio.</Text>
</Dialog>

Props

Se importa con import { Dialog } from '@amset/ui'. Las obligatorias van marcadas.

PropTipoPara qué sirve
titleobligatoriaReactNodeEl titulo. Texto, o un nodo si lleva algo mas (una marca, un recuento): el nombre accesible del dialogo sale de su contenido de texto.
accentstringUn color CSS propio para la cabecera (el icono) cuando ni un tono ni el acento de la marca valen: una seccion con su color. Se escribe en `--amset-dialog-accent`.
actions(close: () => void) => ReactNodeBotones del pie. Recibe `close` para que la accion pueda cerrar el dialogo sin que quien lo usa tenga que llevar el estado.
bodyColumnbooleanEl cuerpo como columna flex: el contenido reparte el alto y lleva su propia zona de desplazamiento, en vez de desplazarse el cuerpo entero.
childrenReactNodeCuerpo del dialogo. Texto corto: si necesita scroll, probablemente sea una pagina. Sin cuerpo (una pregunta que cabe en el titulo y la descripcion) no se pinta el hueco.
classNamestringSe une a las clases de la biblioteca, no las sustituye.
closeLabelstring—
descriptionReactNodeFrase bajo el título, antes del cuerpo. Se usa como descripción accesible. Puede llevar algo más que texto (una etiqueta de estado): se lee su texto.
dismissablebooleanPulsar fuera cierra. Por defecto si, salvo en `kind="alert"`, que nunca se cierra asi. En `false`, el dialogo solo se va por sus botones, Escape o `open`: para un formulario a medias que no debe perderse por un clic de mas (el `maskClosable` de antd).
flushbooleanEl cuerpo sin relleno: contenido que ya lo trae, o que llega hasta los bordes.
footerStartReactNodeContenido extra a la izquierda del pie: un enlace de ayuda, una casilla.
fullbooleanOcupa la ventana entera menos un margen: para un editor o una vista previa.
headerActionsReactNodeBotones en la cabecera, entre el titulo y el aspa de cerrar: una ayuda, un menu.
hideHeaderbooleanSin cabecera visible: el titulo sigue siendo el nombre accesible, pero no se pinta. Para lo que lleva su propio encabezado dentro, como un buscador.
iconReactNodeIcono propio de la cabecera, en lugar del del tono. Hereda el color de `accent` si se da, y si no el del texto.
inlinebooleanLa misma caja pintada EN LA PAGINA: sin `<dialog>`, sin fondo, sin Escape ni trampa de foco y sin aspa. Para reutilizar como panel de una pantalla lo que en otro sitio es un dialogo. `open`, si se da, la muestra o la esconde.
keyboardDismissDisabledbooleanEscape cierra. Por defecto si. Si se apagan los dos, lo que esta DENTRO tiene que ofrecer una salida, o quien no usa raton se queda encerrado.
kind"alert" | "normal"`alert` para confirmaciones destructivas: se anuncia como `alertdialog` y no se cierra pulsando fuera, para que un clic perdido no conteste por nadie. Escape si la cierra, como cancelacion (el patron `alertdialog` de WAI-ARIA): llega a `onOpenChange(false)`, igual que el boton de cancelar.
loadingbooleanEl contenido esta llegando. En lugar de `children` se enseña un esqueleto, y el cuerpo se marca ocupado. El titulo y los botones se quedan: quien lo abrio sabe de que va y puede cerrarlo sin esperar.
loadingTextstringLo que se anuncia al lector mientras carga. Por defecto, «Cargando…».
onClosed() => voidSe ejecuta cuando ha terminado de cerrarse: despues de la animacion de salida, con el dialogo ya fuera de la pagina y el foco devuelto. Tambien cuando lo cierra quien lo controla con `open={false}`.
onOpenChange(open: boolean) => void—
openboolean—
placement"center" | "top"Donde se coloca: en el centro, o pegado arriba (la paleta de mandos, que crece hacia abajo con sus resultados sin moverse).
size"sm" | "md" | "lg"Ancho máximo: 24, 32 o 44 rem.
tone"info" | "success" | "warning" | "error"Color e icono de la cabecera, para confirmaciones y avisos. Sin tono, la cabecera va sin icono.
triggerReactElement<unknown, string | JSXElementConstructor<any>>Elemento que lo abre. Si no se pasa, el dialogo es controlado con `open`.
widthstring | numberUn ancho maximo propio, mas alla de `size`: un numero son pixeles y un texto es una medida CSS (`'60rem'`). Manda sobre `size`.
withCloseButtonbooleanAspa arriba a la derecha. En un diálogo de alerta no se pone: ahí la decisión se toma con los botones, no escapando por la esquina.

Acepta además los atributos del elemento que pinta: className, style, data-*, aria-* y sus eventos.

Mandos

Estas variables CSS son la forma de adaptarlo. Se declaran sobre el selector del componente, no en :root: la hoja las redeclara en la propia regla y una declaración en el mismo elemento gana siempre.

VariablePor defecto
--amset-dialog-width32rem
--amset-dialog-paddingvar(--amset-space-5)
--amset-dialog-radiusvar(--amset-radius-lg)
--amset-dialog-backgroundvar(--amset-surface)
--amset-dialog-slotvar(--amset-space-3)
--amset-dialog-accentcurrentColor

Cómo se cambia

.amset-dialog {
  --amset-dialog-width: ...;
  --amset-dialog-padding: ...;
}

En el banco de pruebas

Cada estado y cada variante, para tocarlos de uno en uno, en su ficha de ui.amset.tech: