Messaging

Dialogs

Confirmation and modal dialogs interrupt the page to ask for a decision or hold a focused task.

Components · Messaging

A dialog sits on a full-screen backdrop and makes the rest of the page inert until it's resolved. Namirial ships two dialog patterns from the same --nm-dialog-* tokens in namirial-theme.css: a compact Confirmation Dialog for yes/no decisions, and a general-purpose Modal Dialog — optionally collapsible — for short focused tasks.

Delete this document?

This action can't be undone.

Overview

Both patterns share the same .nm-dialog card and sit inside a .nm-dialog-backdrop that dims and blocks the page behind them. They differ in scope: a Confirmation Dialog only ever asks for a single yes/no decision; a Modal Dialog can hold any short, focused task.

When to use — Confirmation Dialog

  • Before a destructive or hard-to-reverse action (delete, discard, cancel a subscription).
  • The decision is binary — proceed or don't — and needs no other input.

When to use — Modal Dialog

  • A short, self-contained task that needs the user's full attention (a quick edit form, a single setting, reviewing terms before continuing).
  • Content that's too long for a Confirmation Dialog's single description line but still doesn't warrant its own page.

Consider another component when:

  • The feedback doesn't need to block the page — use Alert or Toast.
  • The content is anchored to a specific trigger and the rest of the page should stay usable — use Popover.

Anatomy

Every dialog is a header (icon, title, close), a body, and a footer of actions, floating on a backdrop. Confirmation Dialog indents its body to align with the title, next to the header icon; Modal Dialog does not.

Tokens and values that drive each part

PartRoleSource
CardFill--nm-dialog-bg (fixed, neutral)
CardBorder--nm-dialog-border — recolored per intent
CardShadow--nm-dialog-shadow (default), --nm-dialog-shadow-2 (confirmation)
CardRadius / padding / gapborder-radius: 24px · padding: 16px · gap: 24px
TitleColor / size--nm-dialog-fg, 20px / 600
Header iconColor--nm-dialog-icon-color — recolored per intent
Close / collapse toggleColor--nm-dialog-fg, opacity: 0.7 hover / 0.5 active
DescriptionColor / size--nm-dialog-fg, 16px / 400
BackdropFill--nm-dialog-backdrop

Sizes (Modal Dialog)

Modal Dialog scales via max-width, defaulting to md. Confirmation Dialog is fixed at its own 480px max-width and doesn't use these size modifiers.

xs/sm
max-width 320px
md
max-width 560px (default)
lg
max-width 800px
xl
max-width 1024px

Intent variants

Both patterns share seven intents that recolor the border and header icon; the card fill always stays neutral (--nm-dialog-bg).

Primary

General-purpose confirmation.

Warning

Flags a caveat before proceeding.

Negative

Confirms a destructive action.

Content types

Confirmation Dialog

Fixed-width, header icon paired with an indented, single-purpose description, and exactly two footer actions — a neutral escape and one committing action.

Delete this document?

This action can't be undone.

General body content, no forced indentation, sized to fit what it holds.

Edit display name

This is how your name appears to other users.

.nm-dialog--collapsible animates its body and footer between shown and .is-collapsed, toggled by .nm-dialog__toggle instead of (or alongside) a close button — useful for "show details" style disclosure inside a modal.

Advanced options

Light & dark theme

--nm-dialog-bg, -fg, -icon-color, and both shadow tokens are explicitly remapped under .dark — the card stays a neutral surface color independent of intent in both themes.

Light data-theme="light"

Delete?

Can't be undone.

Dark data-theme="dark"

Delete?

Can't be undone.

Both previews are locked — they don't follow the page theme switcher.

Do & don't

✓Do

Delete this document?

This can't be undone.

Name the destructive action on the button itself ("Delete"), not a generic "OK."
✕Don't

Are you sure?

Do you want to continue?

Don't use vague titles or Yes/No labels that force the user to re-read the description to know what they're agreeing to.
✓Do

Edit display name

Shown to other users.

Keep a Modal Dialog to one focused task — one form, one decision.
✕Don't

Account settings

A full multi-section settings page doesn't belong stacked inside a modal — give it its own page instead.

Don't nest an entire settings page inside a modal — it removes the URL, back button, and scroll context users expect.

Accessibility

Semantics

  • Give the card role="dialog" (or role="alertdialog" for a Confirmation Dialog on a destructive action), aria-modal="true", and label it with aria-labelledby pointing at .nm-dialog__title.
  • Describe it with aria-describedby pointing at .nm-dialog__description.

Focus

  • On open, move focus to the dialog — the title, the first focusable element, or the least destructive footer action (never the destructive one by default).
  • Trap Tab/Shift+Tab focus inside the dialog while it's open; nothing behind the backdrop should be reachable.
  • On close, return focus to whatever triggered the dialog.

Keyboard

  • Escape closes the dialog, equivalent to the close button — unless the dialog represents an unsavable, irreversible in-progress action.
  • Clicking the backdrop should close the dialog the same way Escape does, unless doing so would silently discard unsaved input.

Labeling

  • Never make the destructive action the visually dominant one by default focus/color alone — pair it with a clear, specific label.

Token reference

TokenRole
--nm-dialog-bgCard fill — fixed, not intent-driven
--nm-dialog-fgTitle and description text color
--nm-dialog-borderCard border — recolored per intent
--nm-dialog-icon-colorHeader icon color — recolored per intent
--nm-dialog-shadowShadow — Confirmation Dialog
--nm-dialog-shadow-2Shadow — Modal Dialog (default)
--nm-dialog-backdropBackdrop fill

Implementation

Open/close state, focus trapping, and backdrop click handling need JavaScript (or the native <dialog> element); the card and backdrop themselves are pure CSS.

<link rel="stylesheet" href="namirial-theme.css">

<div class="nm-dialog-backdrop">
  <div class="nm-dialog nm-dialog--confirmation nm-dialog--negative" role="alertdialog" aria-modal="true" aria-labelledby="dlg-title" aria-describedby="dlg-desc">
    <div class="nm-dialog__header">
      <span class="nm-dialog__header-icon" aria-hidden="true"><!-- icon --></span>
      <h3 class="nm-dialog__title" id="dlg-title">Delete this document?</h3>
    </div>
    <div class="nm-dialog__body">
      <p class="nm-dialog__description" id="dlg-desc">This action can't be undone.</p>
    </div>
    <div class="nm-dialog__footer">
      <button type="button" class="nm-button nm-button--secondary nm-button--md nm-button--ghost">Cancel</button>
      <button type="button" class="nm-button nm-button--negative nm-button--md">Delete</button>
    </div>
  </div>
</div>

CSS classes

ClassValuesDefault
nm-dialog--{size}xs · sm · md · lg · xl — omit for the md default (Modal Dialog only)— (md)
nm-dialog--confirmationFixed-width Confirmation Dialog layout, indented body—
nm-dialog--collapsible + .is-collapsedAnimates body/footer open/closed—
nm-dialog--{intent}primary · secondary · accent · info · positive · negative · warning—
nm-dialog__close / nm-dialog__toggleClose button / collapse toggle, 24×24px—
nm-dialog-backdropFull-screen dimmed backdrop wrapping the card—