Skip to content

Dialog Nuevo

Modal overlay con focus trap, scroll lock y backdrop. Implementa el patrón WAI-ARIA Dialog (Modal) con soporte para modo alertdialog.

Demostración

Sin estilos (solo base.css)

Así se ve hp-dialog usando únicamente @headless-primitives/utils/base.css. El focus trap, scroll lock, ESC para cerrar y todos los atributos ARIA funcionan completamente sin ningún estilo visual.

Contenido del dialog sin estilos. El foco queda atrapado aquí.

Con estilos personalizados

Título del Diálogo

Este es el contenido del diálogo modal. Puedes poner cualquier cosa aquí.

html
<hp-dialog>
  <hp-dialog-trigger>
    <button class="open-dialog">Abrir Diálogo</button>
  </hp-dialog-trigger>
  <hp-dialog-backdrop class="backdrop"></hp-dialog-backdrop>
  <hp-dialog-content class="dialog-content">
    <h2>Título</h2>
    <p>Contenido del diálogo.</p>
    <button onclick="this.closest('hp-dialog').close()">Cerrar</button>
  </hp-dialog-content>
</hp-dialog>
css
.backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
}

.dialog-content {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  max-width: 400px;
  width: 90%;
}

.open-dialog {
  padding: 10px 20px;
  background: var(--vp-c-brand-1);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

Instalación

bash
pnpm add @headless-primitives/dialog
bash
npm install @headless-primitives/dialog
bash
yarn add @headless-primitives/dialog
bash
bun add @headless-primitives/dialog

Features

  • ⌨️ Escape cierra el dialog (deshabilitado en modo alert).
  • ♿️ Focus trap automático, role="dialog" / role="alertdialog" y aria-modal.
  • 🎨 Sin estilos visuales (Headless) — posicionamiento y backdrop via base.css.
  • 🔒 Scroll lock del body mientras el dialog está abierto.
  • 🖱️ Click en backdrop cierra el dialog (deshabilitado en modo alert).

Anatomía

html
<hp-dialog>
  <hp-dialog-trigger></hp-dialog-trigger>
  <hp-dialog-backdrop></hp-dialog-backdrop>
  <hp-dialog-content>
    <hp-dialog-title></hp-dialog-title>
    <hp-dialog-close></hp-dialog-close>
  </hp-dialog-content>
</hp-dialog>

API Reference

hp-dialog

Contenedor principal que coordina trigger, backdrop y content.

Atributos / Propiedades

Atributo / PropiedadTipoPor DefectoDescripción
data-alertbooleanfalseActiva modo alertdialog: ESC no cierra, click en backdrop no cierra.

Eventos

EventoDetalleDescripción
hp-openSe emite cuando el dialog se abre.
hp-closeSe emite cuando el dialog se cierra.

Métodos

MétodoDescripción
open()Abre el dialog programáticamente.
close()Cierra el dialog programáticamente.

hp-dialog-trigger

El elemento que abre el dialog al hacer click.

Atributos / Propiedades

Atributo / PropiedadTipoPor DefectoDescripción
disabledbooleanfalseDeshabilita el trigger.

Atributos ARIA gestionados automáticamente

  • role="button" — Asignado si no se especifica.
  • tabindex="0" — Habilitado cuando no está deshabilitado.
  • aria-expanded"true" cuando el dialog está abierto, "false" cuando cerrado.
  • aria-controls — ID del content cuando abierto.
  • aria-disabled — Sincronizado con el estado disabled.

hp-dialog-content

El contenido modal con focus trap.

Atributos ARIA gestionados automáticamente

  • role="dialog" — O "alertdialog" si hp-dialog tiene data-alert.
  • aria-modal="true" — Siempre presente.
  • aria-hidden"true" cuando cerrado, ausente cuando abierto.
  • data-state"open" | "closed".
  • data-hp-overlay-content — Presente siempre (usado por base.css para posicionamiento fijo).
  • id — Generado automáticamente si no proporcionado.

hp-dialog-backdrop

Overlay visual que bloquea interacción fuera del dialog.

Atributos ARIA gestionados automáticamente

  • data-hp-backdrop — Presente siempre.
  • data-state"open" | "closed".

hp-dialog-title

Título semántico del dialog.

hp-dialog-close

Botón de cierre que emite hp-close al activarse.

Atributos ARIA gestionados automáticamente

  • role="button" — Asignado si no se especifica.
  • tabindex="0" — Siempre focusable.

Accesibilidad

Adhiere al patrón WAI-ARIA APG para Dialog (Modal).

TeclaAcción
EscapeCierra el dialog (deshabilitado en modo alertdialog).
TabNavega entre elementos focusables dentro del dialog (focus trap).
Shift + TabNavega en reversa dentro del focus trap.
Enter / SpaceActiva el trigger para abrir, o el botón de cierre para cerrar.

Ejemplos

Alert Dialog (No Dismissable)

html
<hp-dialog data-alert>
  <hp-dialog-trigger><button>Eliminar cuenta</button></hp-dialog-trigger>
  <hp-dialog-backdrop></hp-dialog-backdrop>
  <hp-dialog-content>
    <hp-dialog-title>¿Estás seguro?</hp-dialog-title>
    <p>Esta acción no se puede deshacer.</p>
    <hp-dialog-close>Cancelar</hp-dialog-close>
  </hp-dialog-content>
</hp-dialog>

Control Programático

javascript
const dialog = document.querySelector("hp-dialog");

// Abrir
dialog.open();

// Cerrar
dialog.close();

// Escuchar eventos
dialog.addEventListener("hp-open", () => console.log("Abierto"));
dialog.addEventListener("hp-close", () => console.log("Cerrado"));

Lanzado bajo la MIT License.