Ejemplos de componentes Tailwind CSS: tres diálogos
Tres diálogos para tareas distintas, con reglas concretas para guardar, cancelar y devolver el foco.
Estos ejemplos de componentes Tailwind CSS muestran tres diálogos: confirmar, editar y consultar detalles. Parte de un diálogo HTML abierto con showModal(), dale un nombre visible y usa Tailwind para el panel, el fondo, el foco y la disposición. Define aparte dónde empieza el foco, cómo se cierra el diálogo y qué cuenta como éxito.
Estos ejemplos de componentes Tailwind CSS muestran tres diálogos: confirmar, editar y consultar detalles. Parte de un diálogo HTML abierto con showModal(), dale un nombre visible y usa Tailwind para el panel, el fondo, el foco y la disposición. Define aparte dónde empieza el foco, cómo se cierra el diálogo y qué cuenta como éxito.
Los ejemplos se sitúan en Fieldnote, un espacio de trabajo ficticio. El proyecto «Lista de lanzamiento» tiene varias vistas guardadas. El equipo necesita quitar una vista, cambiar el nombre del proyecto y explicar por qué está restringido el acceso. Las tres acciones caben en un diálogo, pero piden cosas distintas. Si todas heredan los mismos botones y reglas de cierre, quedan sin resolver decisiones que no dependen del aspecto visual.
Cuándo interrumpir la tarea
Un modal tiene sentido cuando la persona debe resolver una tarea breve o salir de ella de forma explícita antes de volver a la página. El patrón de diálogo modal de WAI describe un diálogo que contiene la navegación con teclado y deja inactiva la interfaz de fondo. Si solo hay que comunicar que un cambio se guardó, mantén a la persona en su tarea y muestra un mensaje de estado. Si necesita comparar varias vistas durante una edición, reserva una página u otro espacio que conserve ese contexto a la vista.


En Fieldnote, quitar una vista compartida requiere una decisión porque dejará de estar disponible para el equipo. Cambiar el nombre pide un campo y un resultado de guardado. Consultar el motivo de una restricción pide una salida clara al terminar de leer. El cuarto caso se resuelve en la página: tras un cambio de nombre normal, una confirmación breve evita abrir otro modal. La guía de mensajes de estado de WAI explica cómo comunicar el cambio sin mover el foco. Deja la región preparada antes de actualizar su texto y comprueba que se anuncie.
Parte del componente Modal de EmviUI si necesitas una referencia para componer el título, el texto y los botones en Figma. La captura del kit muestra una versión con botones en fila y otra con botones apilados, ambas con texto de ejemplo. Duplica esas dos disposiciones y sustituye los textos por las etiquetas completas de tu producto. La captura sirve para comparar espacio y jerarquía; en el navegador habrá que verificar el foco, el cierre y los resultados del guardado.
También conviene preguntar si se puede terminar la tarea sin volver a abrir el diálogo. Cuando se informa de un resultado en la página, aclara qué ha cambiado: «Nombre del proyecto actualizado» aporta más que «Listo». Si el motivo de un permiso aparece en cada visita, pon una explicación breve junto a la acción bloqueada y deja el detalle como opción. Así es la persona quien decide si quiere abrir el modal.
Confirma un cambio irreversible
Antes de pedir una confirmación destructiva, identifica el elemento y explica la consecuencia. «¿Quitar la vista guardada?» y «El proyecto Lista de lanzamiento seguirá disponible. Se quitará la vista compartida Próximos lanzamientos» dejan claro el alcance. Usa «Quitar vista» para confirmar y «Cancelar» para salir sin cambios. Ante una acción difícil de revertir, la guía de foco inicial del APG propone considerar la acción menos destructiva. En este caso, el foco inicial va a Cancelar.

La demostración de archivo que sigue reproduce el comportamiento del navegador sin modificar datos. La especificación HTML del elemento dialog define la apertura modal y el método especial del formulario: al enviar con method="dialog", se cierra el diálogo y se guarda el valor del botón pulsado, sin enviar el formulario al servidor. Una operación real e irreversible necesita una petición explícita y una comprobación del resultado. En este ejemplo los botones no archivan nada.
<button id="open-archive" type="button">Archivar proyecto</button>
<dialog id="archive" aria-labelledby="archive-title"
class="m-auto max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)]
max-w-md overflow-y-auto rounded-xl bg-white p-6 text-slate-900
backdrop:bg-slate-900/50">
<h2 id="archive-title">¿Archivar el proyecto?</h2>
<p>Esta demostración solo guarda tu elección.</p>
<form method="dialog" class="mt-4 grid gap-3 sm:flex sm:justify-end">
<button value="cancel" autofocus class="rounded-lg px-4 py-2
focus-visible:outline-2 focus-visible:outline-offset-2">Cancelar</button>
<button value="archive" class="rounded-lg bg-slate-900 px-4 py-2 text-white
focus-visible:outline-2 focus-visible:outline-offset-2">Archivar</button>
</form>
</dialog>
<script>
const modal = document.querySelector("#archive");
document.querySelector("#open-archive").addEventListener("click", () => {
modal.returnValue = "";
modal.showModal();
});
</script>
El botón de apertura queda fuera del panel. Asignar por tu cuenta el atributo open no equivale a llamar a showModal(). La referencia de variantes de estado de Tailwind documenta los estilos de backdrop y focus-visible usados en el ejemplo. El estilo indica qué control tiene el foco; el elemento nativo establece el límite modal. Comprueba que el contorno se distingue tanto en el botón claro como en el oscuro. Para revisar la combinación de foco y error, consulta la guía de color y foco en formularios Tailwind.
En el caso real de la vista compartida, cierra tras confirmar el éxito, actualiza la lista y mueve el foco a un punto que siga disponible si ha desaparecido el botón original. El encabezado «Vistas guardadas», preparado para recibir foco por código, o la acción de la siguiente fila son dos lugares desde los que se puede continuar. Escape y Cancelar deben dejar la vista intacta. Si vence el tiempo de espera y no sabes si el servidor ejecutó la operación, confirma el resultado antes de ofrecer un reintento.
Prueba con dos accesos distintos al mismo diálogo, por ejemplo desde una fila y desde la barra del proyecto. Si cancelas desde la barra, el foco debería volver allí, no a la primera fila que coincida. Si confirmas desde una fila que desaparece, elige dónde dejar el foco después de actualizar la lista. Anota qué elemento lo recibe en cada caso: servirá cuando otra pantalla reutilice el diálogo.
Permite recuperar una edición
Al cambiar un nombre, empieza por el campo con su etiqueta y conserva el valor actual. Si falla el guardado, conserva también lo que se acaba de escribir. Cuando el nombre se rechaza, muestra el error junto al campo; si falla la conexión, explica qué puede hacer la persona para recuperarse. La interfaz debe seguir mostrando que el cambio está pendiente o que ha fallado. Usa el envío normal de un formulario con un controlador de guardado y cierra al confirmarse el éxito.

Define de antemano qué pasa mientras se guarda. Una segunda pulsación no debería iniciar otra escritura mientras la primera está pendiente. Muestra «Guardando el nombre del proyecto…» y decide qué hará la aplicación si se cierra el panel. Cerrar no cancela una petición que el servidor ya ha aceptado. Si se permite salir mientras espera, deja el resultado visible en la página y actualiza el nombre cuando corresponda. Simula una respuesta lenta y repite con Tab, Mayús+Tab y Escape para comprobar que el foco y el mensaje siguen teniendo sentido.
Un botón Cancelar puede descartar un cambio breve de nombre si esa es la regla del producto y perder ese texto cuesta poco. Para una edición más larga, valora guardar un borrador o permitir revisar antes de salir. Abrir otra confirmación ante cualquier edición pequeña añade pasos. Si quieres ensayar abandono, error y reintento antes de implementar, prueba los ejercicios de recuperación con prototipos de Figma.
En la primera prueba, introduce un nombre que el servidor vaya a rechazar, como uno que ya se usa en ese espacio de trabajo. Comprueba que el texto sigue en el campo y que el error explica el problema. Corrige el valor y vuelve a enviarlo. Luego prueba una pérdida de conexión con un nombre válido. Un duplicado exige elegir otro nombre; un fallo de red exige poder reintentar o averiguar si el servidor llegó a aplicar el cambio.
Facilita la lectura en móvil
Una explicación de acceso de solo lectura necesita un título, varios párrafos y un botón Cerrar. Si hay varias secciones, puedes empezar en el título o en otro elemento estático al principio con tabindex="-1". Así evitas que el foco salte al último botón y desplace fuera de la vista el inicio. La guía del APG para diálogos con contenido estructurado explica esta opción y desaconseja convertir todo el contenido en una única descripción accesible. Usa el título como nombre y deja que se recorran los párrafos y listas por separado.

En una pantalla estrecha, el panel debe caber en el ancho visible y el contenido alto debe poder desplazarse en vertical. La referencia de desbordamiento de Tailwind explica la utilidad que usa la demostración. En el ejemplo corto se desplaza todo el diálogo. Para la explicación larga, prueba una columna flex con cabecera y pie dentro de la estructura y una sola zona central con min-h-0 y overflow-y-auto. Evita sumar un desplazamiento independiente en el panel exterior. En una ventana muy baja, si cabecera y pie dejan sin espacio al cuerpo, permite desplazar todo el panel.
Antes de dar por buena una maqueta, prueba un nombre largo, etiquetas traducidas y zoom. La guía de adaptación del contenido de WAI explica la comprobación a un ancho equivalente a 320 píxeles CSS para contenido de desplazamiento vertical. A ese ancho, las etiquetas y los botones deben ajustarse sin provocar desplazamiento lateral. La guía de tipografía y zoom en Tailwind detalla una prueba independiente para tamaño y espaciado.
En escritorio, empieza por un ancho máximo cómodo y deja que el texto determine la altura del cuerpo. Si el pie queda fijo, llega con Tab a los enlaces del final del área desplazable y verifica que se ve su indicador de foco. Abre también el teclado del móvil al editar el nombre: la altura útil puede reducirse sin que cambie el ancho. Comprueba que se puede llegar a una acción sin cerrar el teclado ni arrastrar la página de fondo.
Comprueba adónde va el foco
Repite la misma secuencia en cada diálogo: abre con teclado, comprueba el foco inicial y el nombre anunciado, recorre los controles en ambos sentidos, sal y comprueba dónde queda el foco. Repite con puntero y en una ventana estrecha. Mientras el modal nativo está abierto, el fondo no debe recibir el foco. Prueba el caso de mayor coste en cada ejemplo: que desaparezca el botón original, que falle el cambio de nombre conservando el texto y que el panel de detalles crezca hasta dejar los controles fuera del área visible.


Redacta resultados observables. «Funciona en móvil» cuesta reproducir; «a 320 píxeles CSS, se alcanza Cerrar con el teclado sin tener que desplazar el contenido lateralmente» da a quien revisa una prueba concreta. Anota el navegador, el tamaño de la ventana, el zoom, el idioma y los datos iniciales. Restaura el proyecto y la vista guardada entre pruebas para empezar el segundo intento con las mismas acciones disponibles.
Prepara un registro sencillo con cuatro columnas: control de apertura, foco inicial esperado, acción de salida y destino del foco. Añade filas para Escape, Cancelar, eliminación completada y guardado rechazado. Tras un rechazo, la persona sigue en el diálogo con el error claro y el campo disponible. Tras quitar la vista, el foco va al elemento que sigue en la lista. Puedes revisar estas reglas al lado de la muestra de Figma.
La cuadrícula de tarjetas de EmviUI muestra una variante habitual de esta prueba: se repite el mismo control junto a elementos distintos. Si adaptas las tarjetas para añadir un botón Ver detalles, abre la segunda y cierra el diálogo. El foco debe volver a ese botón concreto, aunque la primera tarjeta tenga la misma etiqueta visible. Repite tras filtrar la cuadrícula de modo que desaparezca la tarjeta de origen y comprueba que el destino alternativo lleva a los resultados actualizados.
Pablo Mayoral
Diseñador UX/UI y Web con más de 10 años de experiencia. Creador de EmviUI (sistema de diseño en Figma con más de 10k componentes), UImand y Vitamin Bootstrap. Diseñando actualmente productos digitales en CQMRewards.