Overview of the Phoenix and LiveView Headless Dialog Component
The Mishka Chelekom Headless Dialog
ships zero opinionated styling
- only the semantic markup, full WAI-ARIA
wiring, a focus trap, scroll lock, and paired-presence state
(
data-open
/
data-closed
).
Every part - trigger, backdrop, viewport, popup, title, description,
content
and footer
- is
addressable through a
*_class
attribute, so you style it entirely with your own Tailwind
classes while
the accessibility and behavior keep working underneath.
Base UI Dialog example (Phoenix headless)
<.dialog id="baseui-dialog-hero" trigger_class="flex h-8 items-center justify-center gap-2 border border-neutral-950 dark:border-white bg-white dark:bg-neutral-950 px-3 text-sm font-normal text-neutral-950 dark:text-white select-none hover:bg-neutral-100 dark:hover:bg-neutral-800" backdrop_class="fixed inset-0 min-h-dvh bg-black opacity-20 transition-opacity duration-150 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0 dark:opacity-50" popup_class="fixed top-1/2 left-1/2 -mt-8 flex w-96 max-w-[calc(100vw-3rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 bg-white dark:bg-neutral-950 p-4 text-neutral-950 dark:text-white border border-neutral-950 dark:border-white shadow-[0.25rem_0.25rem_0] shadow-black/12 transition-[scale,opacity] duration-100 ease-out data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0" title_class="text-base font-bold" description_class="text-sm text-neutral-600 dark:text-neutral-400" footer_class="flex justify-end gap-3" > <:trigger>View notifications</:trigger> <:title>Notifications</:title> <:description>You are all caught up. Good job!</:description> <:close> <button type="button" data-close class="flex h-8 items-center gap-2 border border-neutral-950 dark:border-white bg-white dark:bg-neutral-950 px-3 text-sm text-neutral-950 dark:text-white hover:bg-neutral-100 dark:hover:bg-neutral-800" > Close </button> </:close> </.dialog>
Parts & data attributes
Each part carries a stable
data-part
and a structural
chelekom-dialog__*
class you can target, plus paired-presence state for open/closed transitions.
| Part | data-part | State / ARIA | Purpose |
|---|---|---|---|
| Trigger | trigger | aria-haspopup, aria-expanded, data-popup-open | The button that opens the dialog. |
| Backdrop | backdrop | data-open, data-closed, data-starting-style, data-ending-style | The overlay behind the popup; carries the transition state. |
| Popup | popup | role="dialog", focus-trapped | The dialog panel itself. |
| Title / Description | title / description | aria-labelledby / aria-describedby | Announced to screen readers; wired automatically. |
Accessibility
Follows the
WAI-ARIA Dialog (Modal) pattern
: focus is trapped inside the open dialog and restored to the trigger on close,
Escape
closes it, and an outside click dismisses it (both configurable). The title and
description slots are announced to screen readers.