Dialog
Modal dialog for confirmations, forms, and alerts. Uses the native <dialog> element opened with showModal().
Titled variants expose a Title (and optional Description). Bare variants name the dialog with aria-label (and optional aria-description) instead.
React/Vue require Root for id context. HTML usually wraps Trigger + Content in a div, but the core keys off the mct:dialog-open / mcc:dialog / mct:dialog-close ids.
Composition
Root (optional in HTML; required for React/Vue)
Trigger
Content
Title (titled variants)
Description (optional even when titled)
Close (typically one)
(optional body)Usage
HTML
<button
type="button"
id="mct:dialog-open:notice"
aria-haspopup="dialog"
aria-controls="mcc:dialog:notice"
>
Open dialog
</button>
<dialog
id="mcc:dialog:notice"
aria-labelledby="mcc:dialog-title:notice"
aria-describedby="mcc:dialog-description:notice"
tabindex="-1"
>
<h2 id="mcc:dialog-title:notice">Heads up</h2>
<p id="mcc:dialog-description:notice">
This is a modal dialog. Press Escape or use the close button to dismiss.
</p>
<button type="button" id="mct:dialog-close:notice">Close</button>
</dialog>React
import { Dialog } from "@monochrome-ui/react"
<Dialog.Root>
<Dialog.Trigger>Open dialog</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Heads up</Dialog.Title>
<Dialog.Description>
This is a modal dialog. Press Escape or use the close button to dismiss.
</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
</Dialog.Content>
</Dialog.Root>Vue
<script setup lang="ts">
import { Dialog } from "@monochrome-ui/vue"
</script>
<template>
<Dialog.Root>
<Dialog.Trigger>Open dialog</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Heads up</Dialog.Title>
<Dialog.Description>
This is a modal dialog. Press Escape or use the close button to dismiss.
</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
</Dialog.Content>
</Dialog.Root>
</template>Parts
Root
Optional in HTML; required for React/Vue (context). Element: div. Children: Trigger then Content.
Trigger
Required. Element: button.
| Kind | Name | Type / value | Default | Description |
|---|---|---|---|---|
| attr | type |
"button" |
||
| attr | id |
mct:dialog-open:<id> |
||
| attr | aria-haspopup |
"dialog" |
||
| attr | aria-controls |
mcc:dialog:<id> |
||
| attr | aria-disabled |
"true" | absent |
absent | When "true", core ignores open attempts. |
| prop | disabled |
boolean |
false |
Applies aria-disabled on the trigger. |
Trigger never carries aria-label or aria-description for bare dialogs.
Content
Required. Element: dialog. Children: Title? Description? Close (and optional body).
| Kind | Name | Type / value | Default | Description |
|---|---|---|---|---|
| attr | id |
mcc:dialog:<id> |
||
| attr | tabindex |
"-1" |
||
| attr | role |
"alertdialog" | absent |
absent | Blocking alert semantics. |
| attr | aria-labelledby |
mcc:dialog-title:<id> | absent |
Titled variants with a Title. Omit for bare (aria-label). |
|
| attr | aria-describedby |
mcc:dialog-description:<id> | absent |
When a Description is present (HTML), or whenever wrappers have not received aria-description. |
|
| attr | aria-label |
string | absent | Accessible name for bare variants. | |
| attr | aria-description |
string | absent | Accessible description for bare variants; also clears wrapper default aria-describedby. |
|
| prop | role |
"alertdialog" | absent |
absent | Same as the role attribute. |
| prop | aria-label |
string | absent | Switches Content into bare labelling (skips aria-labelledby). |
|
| prop | aria-description |
string | absent | Bare description (skips aria-describedby in wrappers). |
Title
Optional (titled variants; omit for bare). Element: h2 (or h1-h6).
| Kind | Name | Type / value | Default | Description |
|---|---|---|---|---|
| attr | id |
mcc:dialog-title:<id> |
||
| prop | as |
"h1" … "h6" |
"h2" |
Heading level. Change only to match the page outline. |
Description
Optional even for titled; omit for bare and title-only. Element: p.
| Kind | Name | Type / value | Description |
|---|---|---|---|
| attr | id |
mcc:dialog-description:<id> |
Close
Required (typically one). Element: button.
| Kind | Name | Type / value | Description |
|---|---|---|---|
| attr | type |
"button" |
|
| attr | id |
mct:dialog-close:<id> |
Same <id> as the open trigger / content when using a single close. Multiple closes need distinct ids under the mct:dialog-c prefix; do not duplicate the same id. |
Notes
- Titled: Content has
aria-labelledbypointing at Title. Include Title. Description andaria-describedbyare optional; add them when a description is present (HTML may omit both Description andaria-describedby, as in form fixtures). - alertdialog (titled): Same labelling as titled, plus
role="alertdialog"on Content. - bare: Omit Title and Description; set
aria-labelon Content. - bare-alertdialog: Bare labelling plus
role="alertdialog". - HTML bare: Omit
aria-labelledbyandaria-describedby; addaria-descriptiononly when needed. - Wrappers bare:
aria-labelskipsaria-labelledby.aria-describedbyis still emitted unlessaria-descriptionis passed. Passaria-descriptionwhen you need a description, or accept a dangling describedby id if you omit it. - Disabled:
aria-disabled="true"on Trigger (HTML) or Triggerdisabled(wrappers); core will not open. - Open behavior: Core calls
showModal(). Only one dialog at a time; opening is a no-op if another is already open. Initial focus follows the HTML dialog focusing steps (autofocus, then first focusable, then the dialog). - Close: Close control, Escape (after tooltips/menus/popovers), or native dialog close. Focus returns to the open trigger.
Keyboard
| Key | Behavior |
|---|---|
| Enter / Space on Trigger | Open (synthesized click) |
| Enter / Space on Close | Close |
| Escape | Close open dialog (after dismissing tooltip / menu / popover layers) |
| Tab | Native modal focus trap inside <dialog> |