Skip to content
HHydro UIdocs
Navigate
ComponentsDialog
ImplementedOverlay / modal

Dialog

Temporarily interrupt a task with modal content and managed focus.

Interactive

Try it

open, strategy, dismissible
Open settingsSettingsUpdate your preferences.Cancel
Live previewReady
MarkupStateEvents
<hui-dialog id="playground-dialog" strategy="native">
  <hui-dialog-trigger>Open settings</hui-dialog-trigger>
  <hui-dialog-content>
    <hui-dialog-title>Settings</hui-dialog-title>
    <hui-dialog-description>Update your preferences.</hui-dialog-description>
    <label>Display name <input value="Ada" /></label>
    <hui-dialog-close>Cancel</hui-dialog-close>
  </hui-dialog-content>
</hui-dialog>
data-state
Waiting for enhancement

No component events yet.

Usage

Use hui-dialog for modal content that temporarily interrupts the current task and requires focus containment. Use a popover for supplemental non-modal content. Do not use a dialog for routine page content or a tooltip-sized description.

Anatomy

  • Root: hui-dialog
  • Trigger: hui-dialog-trigger
  • Content surface: hui-dialog-content
  • Heading and description: hui-dialog-title, hui-dialog-description
  • Close control: hui-dialog-close
  • Manual strategy overlay: [data-part="overlay"]

Examples

Fixture exampleSource-backed
<section aria-labelledby="dialog-heading">
    <h2 id="dialog-heading">Account settings</h2>
    <hui-dialog id="account-dialog">
      <hui-dialog-trigger><b>Account settings</b></hui-dialog-trigger>
      <hui-dialog-content>
        <hui-dialog-title>Account settings</hui-dialog-title>
        <hui-dialog-description>Update your account preferences.</hui-dialog-description>
        <button data-autofocus type="button">Save changes</button>
        <hui-dialog-close>Cancel</hui-dialog-close>
      </hui-dialog-content>
    </hui-dialog>

    <div class="dialog-clip">
      <hui-dialog id="manual-dialog" strategy="manual">
        <hui-dialog-trigger>Manual dialog</hui-dialog-trigger>
        <hui-dialog-content aria-label="Manual dialog">
          <p>Manual modal content.</p>
          <hui-dialog-close>Close manual dialog</hui-dialog-close>
        </hui-dialog-content>
      </hui-dialog>
    </div>
  </section>

API reference

AttributeBindingExposed stateEvent
Root open booleanRoot data-state; content hidden; native/manual dialog open state`data-state="openclosed"; triggeraria-expanded`
Root default-openSeeds open once during enhancementSame as openNone
Root strategySelects native or manual substrateContent data-strategyNone
Root dismissibleControls Escape, backdrop, and overlay dismissalNoneNone
Root aria-label, aria-labelledby, aria-describedbyTrigger/content accessible names and descriptionsGuarded ARIA referencesNone
Content roleDefaults to dialog; may be explicitly set to nonearia-modal="true" for dialog semanticsNone
Content/title/description IDsExisting IDs are preserved; generated IDs use the root IDaria-labelledby / aria-describedbyNone

All state writes use root attributes. Closed content has an inline hidden attribute. Content IDs and references are omitted when they cannot be resolved, preventing dangling ARIA relationships.

When motion is allowed, closing content first exposes data-state="closed", aria-hidden, and inert state, then applies hidden after the surface exit completes. Manual overlay teardown and native dialog close are coordinated with that presence lifecycle. Reduced-motion and no-transition environments apply the closed state immediately.

States and styling

StateContract and styling guidance
DefaultClosed content is hidden and the trigger exposes aria-expanded="false".
HoverUse --hui-color-interactive-hover for trigger feedback.
ActiveUse --hui-color-interactive-active for pressed trigger feedback.
FocusKeep a visible focus ring with --hui-color-focus-ring and restore focus to the trigger on close.
DisabledDisable the trigger and close controls with --hui-color-disabled-background and --hui-color-disabled.
ErrorDialog has no built-in validation state; use aria-invalid and --hui-color-danger on invalid controls inside it.
State channel

Attributes are the source of truth. Style derived state with data-state, ARIA attributes, and the --hui-* token aliases.

Accessibility and keyboard support

Key/actionResult
Trigger Enter/Space/clickToggle dialog and focus the autofocus target, first tabbable, or content
Tab / Shift+Tab while manual dialog is openCycle within the dialog focus scope
EscapeClose and restore focus to the trigger unless dismissible="false"
Close buttonClose and restore focus to the trigger
Outside overlay clickClose unless dismissible="false"
Native dialog cancel/backdrop interactionClose unless dismissible="false"

The dialog is modal: scroll is locked and siblings outside the dialog path are inert while open. Native mode delegates modal behavior to the platform and manual mode uses the shared focus trap.

SSR and forms

  • SSR emits closed content with hidden="hidden", role="dialog", aria-modal="true", deterministic IDs, and no hydro-reactive-* or two-way markers.
  • default-open resolves to open SSR state. Client native mode promotes the content into the top layer during hydration; manual mode portals it after enhancement.
  • SSR never calls showModal(), portals, locks scroll, or marks siblings inert.
  • A root with an explicit id receives stable -content, -title, and -description relationships. Id-less roots omit generated IDs and dependent ARIA references.
  • Without JavaScript, the trigger remains a native button and the content remains hidden. Consumers can use default-open for a progressive initially-open fallback; modal focus and dismissal require JavaScript.

Code

<hui-dialog id="settings">
  <hui-dialog-trigger>Settings</hui-dialog-trigger>
  <hui-dialog-content>
    <hui-dialog-title>Settings</hui-dialog-title>
    <hui-dialog-description>Update your preferences.</hui-dialog-description>
    <button type="button">Save</button>
    <hui-dialog-close>Cancel</hui-dialog-close>
  </hui-dialog-content>
</hui-dialog>
<hui-dialog id="playground-dialog" strategy="native">
  <hui-dialog-trigger>Open settings</hui-dialog-trigger>
  <hui-dialog-content>
    <hui-dialog-title>Settings</hui-dialog-title>
    <hui-dialog-description>Update your preferences.</hui-dialog-description>
    <label>Display name <input value="Ada" /></label>
    <hui-dialog-close>Cancel</hui-dialog-close>
  </hui-dialog-content>
</hui-dialog>