AuroraUI. Components. Overlay
(Aurora UI v0.1.1)
View Source
Overlay family — modal dialog/1, alert_dialog/1, and drawer/1.
Overlays are the kit's highest-risk components for accessibility, so they are
built on the platform first: every overlay is a native <dialog> element and
the JavaScript hook only enhances it (open/close, focus trap, focus return,
scroll lock, background inert, and Escape handling). Getting focus wrong
strands keyboard and screen-reader users, so the rules below are not optional.
Focus management (owned by the hooks)
- Open — the hook calls
showModal()(modal) orshow()(non-modal) and moves focus to the element markedautofocus, else the first tabbable control, else the dialog box. - Trap — modal overlays (
dialog,alert_dialog, and a modaldrawer) keep Tab/Shift+Tab inside the box and mark the rest of the pageinert. - Return — on close focus returns to the element that was focused before the overlay opened (the trigger).
- Escape — closes a dialog / cancels an
alert_dialog/ closes a drawer.alert_dialogis never dismissed by clicking the backdrop; Escape still routes through the cancel action so the app can react.
Scrolling
Long or zoomed content scrolls inside the overlay body. The title, close control, and footer actions stay pinned so they can never be pushed offscreen.
DOM contract
Roots carry data-aui (for the shared focus ring, reduced-motion, and
forced-colors base rules), a stable id (hook target), and:
| Component | phx-hook | data attributes |
|---|---|---|
dialog / alert_dialog | AuroraDialog | data-aui-dialog, data-aui-open, [data-aui-dialog-close] |
drawer | AuroraDrawer | data-aui-drawer, data-aui-side, data-aui-modal, [data-aui-drawer-close] |
Summary
Functions
A confirmation dialog with role="alertdialog".
A modal dialog built on the native <dialog> element.
A sheet that slides in from a side (start/end/top/bottom).
Functions
A confirmation dialog with role="alertdialog".
Unlike dialog/1 it requires an explicit confirm and cancel action,
puts initial focus on the least destructive action (Cancel), and is not
dismissable by clicking the backdrop. Escape still routes through on_cancel
so nothing is silently discarded.
Examples
<.alert_dialog
id="del"
open={@confirming}
on_confirm={JS.push("delete")}
on_cancel={JS.push("cancel_delete")}
confirm_label="Delete project"
>
<:title>Delete this project?</:title>
<:description>This permanently removes 3 sites and cannot be undone.</:description>
</.alert_dialog>Attributes
id(:string) - Defaults tonil.open(:boolean) - Defaults tofalse.size(:string) - Defaults to"sm". Must be one of"sm","md","lg", or"xl".on_confirm(:any) (required) - JS command or event for the confirming action.on_cancel(:any) - JS command or event for the cancelling action; also runs on Escape. Defaults tonil.confirm_label(:string) - Defaults to"Confirm".cancel_label(:string) - Defaults to"Cancel".confirm_variant(:string) - visual weight of the confirm button; the destructive default isdanger. Defaults to"danger". Must be one of"primary", or"danger".- Global attributes are accepted.
Slots
title(required)description(required) - explain the consequence; wired via aria-describedby.inner_block- optional extra body content.
A modal dialog built on the native <dialog> element.
Focus is trapped while open, the background is made inert, body scroll is
locked, and focus returns to the trigger on close. Provide on_close so the
server can clear the controlling assign when the user dismisses via Escape,
the backdrop, or the close control.
When not to use
For a destructive confirmation reach for alert_dialog/1 (it forces an
explicit choice and is not click-away dismissable). For non-modal contextual
content use AuroraUI.Components.Floating.popover/1.
Examples
<.dialog id="invite" open={@show_invite} on_close={JS.push("close_invite")}>
<:title>Invite teammates</:title>
<:description>They'll get an email with a join link.</:description>
<.field ... />
<:footer>
<.button variant="ghost" data-aui-dialog-close>Cancel</.button>
<.button phx-click="send_invite">Send invites</.button>
</:footer>
</.dialog>Attributes
id(:string) - stable id; auto-generated when omitted. Defaults tonil.open(:boolean) - controlled open state; reflected as data-aui-open for the hook. Defaults tofalse.on_close(:any) - a Phoenix.LiveView.JS command or event name run when the dialog requests close. Defaults tonil.dismissable(:boolean) - when true, clicking the backdrop closes the dialog. Defaults totrue.size(:string) - max-width of the box. Defaults to"md". Must be one of"sm","md","lg", or"xl".- Global attributes are accepted.
Slots
title(required) - accessible name; wired via aria-labelledby.description- supporting copy; wired via aria-describedby.inner_block(required) - dialog body (scrolls when tall).footer- pinned action row.
A sheet that slides in from a side (start/end/top/bottom).
Modal vs non-modal
modal={true}(default) — behaves likedialog/1: focus is trapped inside the sheet, the rest of the page isinert, a backdrop is shown, and Escape/backdrop close it. Use for tasks that must be completed or abandoned.modal={false}— the sheet opens withshow()(notshowModal()), so focus is not trapped and the background stays fully interactive with no backdrop. Use for inspectors/filters the user works alongside the page.
The exit transition is played by the hook before the element is removed, so it never races LiveView DOM patching.
Examples
<.drawer id="filters" side="end" modal={false} open={@show_filters}>
<:title>Filters</:title>
...filter controls...
</.drawer>Attributes
id(:string) - Defaults tonil.open(:boolean) - Defaults tofalse.side(:string) - logical edge the sheet slides from (start/end honor writing direction). Defaults to"end". Must be one of"start","end","top", or"bottom".modal(:boolean) - modal drawers trap focus and inert the page; non-modal drawers do neither. Defaults totrue.on_close(:any) - Defaults tonil.dismissable(:boolean) - Defaults totrue.- Global attributes are accepted.
Slots
title(required)descriptioninner_block(required)footer