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) or show() (non-modal) and moves focus to the element marked autofocus, else the first tabbable control, else the dialog box.
  • Trap — modal overlays (dialog, alert_dialog, and a modal drawer) keep Tab/Shift+Tab inside the box and mark the rest of the page inert.
  • 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_dialog is 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:

Componentphx-hookdata attributes
dialog / alert_dialogAuroraDialogdata-aui-dialog, data-aui-open, [data-aui-dialog-close]
drawerAuroraDrawerdata-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

alert_dialog(assigns)

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 to nil.
  • open (:boolean) - Defaults to false.
  • 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 to nil.
  • confirm_label (:string) - Defaults to "Confirm".
  • cancel_label (:string) - Defaults to "Cancel".
  • confirm_variant (:string) - visual weight of the confirm button; the destructive default is danger. 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.

dialog(assigns)

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 to nil.
  • open (:boolean) - controlled open state; reflected as data-aui-open for the hook. Defaults to false.
  • on_close (:any) - a Phoenix.LiveView.JS command or event name run when the dialog requests close. Defaults to nil.
  • dismissable (:boolean) - when true, clicking the backdrop closes the dialog. Defaults to true.
  • 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.

drawer(assigns)

A sheet that slides in from a side (start/end/top/bottom).

Modal vs non-modal

  • modal={true} (default) — behaves like dialog/1: focus is trapped inside the sheet, the rest of the page is inert, a backdrop is shown, and Escape/backdrop close it. Use for tasks that must be completed or abandoned.
  • modal={false} — the sheet opens with show() (not showModal()), 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 to nil.
  • open (:boolean) - Defaults to false.
  • 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 to true.
  • on_close (:any) - Defaults to nil.
  • dismissable (:boolean) - Defaults to true.
  • Global attributes are accepted.

Slots

  • title (required)
  • description
  • inner_block (required)
  • footer