NativeDialog
Trigger, content and close parts around a native, initially closed `<dialog>`. 0 kB client JS, at most 0.5 kB gzipped.
Anatomy
<NativeDialog.Trigger target="settings">Open</NativeDialog.Trigger>
<NativeDialog.Content aria-labelledby="settings-title" id="settings">
<h2 id="settings-title">Settings</h2>
<NativeDialog.Close target="settings">Close</NativeDialog.Close>
</NativeDialog.Content>Live demo
This demo also runs with JavaScript disabled.
NativeDialog.Trigger
Renders NativeInvoker. Emits command="show-modal", commandfor={target}, class="uiify-native-dialog-trigger".
| Prop | Type | Default | Description |
|---|---|---|---|
target | string | — | Required. `id` of the `NativeDialog.Content` this button opens; the browser resolves it at click time. |
as | NativeButtonAs<TAs> | "button" | See NativeInvoker. |
NativeDialog.Content
Renders <dialog>. Emits class="uiify-native-dialog-content"; `open` and `popover` are omitted from the prop type — a native part is always initially closed.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Required. Unique id supplied by the consumer; referenced by trigger and close `target`. |
aria-labelledby | string | — | Required unless `aria-label` is given — exactly one of the two, enforced by the type. |
aria-label | string | — | Required unless `aria-labelledby` is given. |
NativeDialog.Close
Renders NativeInvoker. Emits command="request-close", commandfor={target}, class="uiify-native-dialog-close".
| Prop | Type | Default | Description |
|---|---|---|---|
target | string | — | Required. `id` of the `NativeDialog.Content` this button closes. |
as | NativeButtonAs<TAs> | "button" | See NativeInvoker. |
Rendered DOM
<button type="button" command="show-modal" commandfor="settings" class="uiify-native-dialog-trigger">Open</button><dialog aria-labelledby="settings-title" id="settings" class="uiify-native-dialog-content"><h2 id="settings-title">Settings</h2><button type="button" command="request-close" commandfor="settings" class="uiify-native-dialog-close">Close</button></dialog>CSS contract
dialog:modal {
/* true while open and blocking interaction */
}
dialog[open] {
/* true while open, native or via defaultOpen */
}Build your own
import { NativeDialog } from "@gunkin/uiify/elements/native-dialog";
export function ConfirmDialog() {
return (
<>
<NativeDialog.Trigger target="delete-confirm">Delete project</NativeDialog.Trigger>
<NativeDialog.Content aria-labelledby="delete-confirm-title" id="delete-confirm">
<h2 id="delete-confirm-title">Delete this project?</h2>
<p>This cannot be undone.</p>
<NativeDialog.Close target="delete-confirm">Cancel</NativeDialog.Close>
<NativeDialog.Close target="delete-confirm">Delete</NativeDialog.Close>
</NativeDialog.Content>
</>
);
}
Used by
Gotchas
- `id` must be stable across server and client renders — `NativeDialog.Trigger`/`NativeDialog.Close`'s `target` has to match it exactly.
- Omitting both `aria-labelledby` and `aria-label` on `NativeDialog.Content` is a type error, not a runtime check — an unnamed `<dialog>` has no ARIA fallback.
- WebKit does not restore focus to the trigger after the dialog closes — a platform gap, not a bug in this element.
- `NativeDialog.Close` sends `request-close`, so the cancelable `cancel` event fires before the dialog closes.
Import
import { NativeDialog } from "@gunkin/uiify/elements/native-dialog";