Dialog
Modal dialog with focus trapping, dismissal, and ARIA wiring from the Zag.js dialog machine.
Primitive · overlay
Install
Section titled “Install”npx shadcn@latest add https://ndigo.dev/r/dialog.jsonTo use the shorter @ndigo/dialog form, configure the namespace in components.json.
| Source | Target | Type |
|---|---|---|
registry/ui/dialog/nd-dialog.ts |
@ui/nd-dialog/nd-dialog.ts |
registry:ui |
registry/ui/dialog/nd-dialog.css |
@ui/nd-dialog/nd-dialog.css |
registry:file |
Live example
Section titled “Live example”See this component rendered live on the live examples page.
Dependencies
Section titled “Dependencies”Registry: Ndigo element foundation.
Packages: @zag-js/dialog@~1.47.0 (installed automatically).
Documentation
Section titled “Documentation”<nd-dialog> wraps the platform-native modal pattern with Zag’s focus trap,
dismissal handling, and ARIA wiring. Markup is yours; behaviour is the machine.
Markup
Section titled “Markup”<nd-dialog> <button data-part="trigger">Invite teammate</button> <div data-part="content"> <h2 data-part="title">Invite teammate</h2> <p data-part="description">They will receive an email invitation.</p> <button data-part="close-trigger">Close</button> <p>Your own body content goes here.</p> </div></nd-dialog>A missing trigger is created from trigger-label (or Open dialog). Missing
content, positioner, and backdrop wrappers are created on connect, so the
short form with body markup alone also works.
| Part | Element | Purpose |
|---|---|---|
trigger |
button |
Opens the dialog; carries aria-haspopup/aria-expanded |
backdrop |
div |
Full-viewport scrim |
positioner |
div |
Fixed positioning context |
content |
div |
Dialog surface; carries role="dialog" |
title |
any | Labelled by aria-labelledby |
description |
any | Described by aria-describedby |
close-trigger |
button |
Closes the dialog |
Attributes
Section titled “Attributes”| Attribute | Type | Description |
|---|---|---|
open |
boolean |
Controlled open state; reflected by the element |
trigger-label |
string |
Label for the generated trigger |
initial-focus |
string |
Selector for the element focused on open |
Events
Section titled “Events”nd-open-change—detail: { open: boolean }, emitted when the dialog opens or closes.
Methods
Section titled “Methods”show()/hide()— open or close programmatically without a trigger.
Styling
Section titled “Styling”Import nd-dialog.css and the design tokens. Every visual value is a --nd-*
token; override the tokens rather than the selectors.
Accessibility
Section titled “Accessibility”Zag owns focus trapping, initial focus, focus restore, Escape, outside-click
dismissal, body scroll locking, and the aria-modal/labelledby/describedby
contract. Provide a title or an aria-label on the element.