0.1.0

Dialog

Dialogs interrupt the page to capture a decision or short form. They trap focus and return it when dismissed.

Try it

Usage

Register dialogs with installDialogs, then open them imperatively via openDialog or a trigger with data-dialog-open. Compose title, body, and actions with the sub-components.

import {
  RuiDialog,
  RuiDialogTitle,
  RuiDialogBody,
  RuiDialogActions,
  RuiDialogClose,
  installDialogs,
  openDialog,
} from '@ecopages/radiant-ui/dialog';
 
installDialogs();
 
<RuiDialog id="edit-profile" label="Edit profile">
  <RuiDialogTitle>Edit profile</RuiDialogTitle>
  <RuiDialogBody>Update your display name and email.</RuiDialogBody>
  <RuiDialogActions>
    <RuiDialogClose>Cancel</RuiDialogClose>
    <button type="button">Save</button>
  </RuiDialogActions>
</RuiDialog>

Custom markup

<rui-dialog> coordinates any light-DOM tree that matches its query contract. The Rui* helpers stamp these targets; they are not required.

import '@ecopages/radiant-ui/dialog';
 
<rui-dialog open label="Edit profile">
  <div data-ref="root" class="rui-dialog">
    <div data-ref="backdrop" class="rui-dialog__backdrop"></div>
    <div data-ref="dialog" class="rui-dialog__surface" role="dialog" aria-modal="true" tabindex={-1}>
      <button type="button" data-dialog-close class="rui-dialog__close"></button>
      <div data-dialog-title class="rui-dialog__title">Edit profile</div>
      <div data-dialog-body class="rui-dialog__body">Update your display name and email.</div>
    </div>
  </div>
</rui-dialog>;

BEM classes are presentation-only. Set alert on the host for role="alertdialog" on [data-ref="dialog"].

Alert dialogs

Set alert to true for destructive confirmations. Alert dialogs limit tab order to the dialog actions.

Delete project?
This removes the project and its files. This cannot be undone.

Return focus on close

Focus returns to the element that opened the dialog. Avoid stacking multiple modal layers.

Theming

Dialog surfaces map to semantic surface roles, never Tailwind palette steps. Override --rui-dialog-* on rui-dialog.

PartDefaultOverride
Backdropoverlay scrimtheme --color-overlay
Surface fill / radius / shadow--background, --radius-container, --shadow-modal--rui-dialog-surface, --rui-dialog-radius, --rui-dialog-shadow
Surface padding / max width--space-inset, 28rem--rui-dialog-padding, --rui-dialog-max-width
Narrow viewport inset1rem--rui-dialog-inset-x
Titleon-backgroundtheme
Close buttonon-surfacetheme
rui-dialog {
  --rui-dialog-max-width: 40rem;
  --rui-dialog-padding: var(--space-6);
}

Accessibility

  • Every dialog needs an accessible name via label or RuiDialogTitle.
  • Use alert for confirmations that require an explicit decision before continuing.
  • Do not open a dialog without a clear way to dismiss it; provide a close action.

API

RuiDialog is a custom element (<rui-dialog>) with a composition-first surface. Pass title / actions for the composite API, or compose the view helpers as children.

Attributes (<rui-dialog>)

AttributeTypeDefaultDescription
openbooleanfalseWhether the dialog is open.
alertbooleanfalseUses role="alertdialog" for workflow-interrupting confirmations.
labelstring''Accessible name when there is no visible title.

Light-DOM contract

TargetRequiredHost writesAuthor owns
[data-ref="root"]yeshidden when closedthe wrapper node
[data-ref="backdrop"]yes—the scrim node; click dismisses
[data-ref="dialog"]yesaria-labelledby, aria-label, aria-describedbyrole, aria-modal, tabIndex (view seeds these)
[data-dialog-title]noid, aria-labelledby wiringvisible title text
[data-dialog-body]noid, aria-describedby wiringbody content
[data-dialog-close]no—dismiss control; click emits rui-close

Do not set hidden on [data-ref="root"] or aria-* on [data-ref="dialog"]. Nested hosts: none.

Events

EventDetailDescription
rui-close{ reason: 'escape' | 'backdrop' | 'dismiss' }Emitted when the dialog is dismissed.

View helpers

ComponentTarget stampedNotes
RuiDialogDialogShell targetsPass title / actions for composite API, or compose helpers as children.
RuiDialogTitle[data-dialog-title], data-ref="title"Visible accessible name.
RuiDialogBody[data-dialog-body], data-ref="description"aria-describedby target.
RuiDialogActions—Action row; not queried by the host.
RuiDialogClose[data-dialog-close], data-ref="close"Emits rui-close with reason dismiss.

CSS classes

Public BEM classes (documented via @cssclass):

ClassDescription
.rui-dialogRoot; hidden until open.
.rui-dialog__backdropScrim using the overlay role.
.rui-dialog__surfaceModal panel: background + rounded-container + shadow-modal.
.rui-dialog__titleDialog title; aria-labelledby target.
.rui-dialog__bodyDialog body; aria-describedby target.
.rui-dialog__actionsRight-aligned action row.
.rui-dialog__closeDismiss button.

Theme roles

PartCSS variables consumed
Backdrop--overlay
Surface--background, --on-background, --shadow-modal, --radius-container, --p-inset
Close button--on-surface