Dialog

Styled modal over the headless overlay - scrim, focus trap, scroll lock.

Dialog playground

Esc, the scrim and the close button all dismiss it.

Install Dialog

1. New project? One command installs the package and wires everything - see Installation:

bash
pnpm dlx zyncat-ui init

2. Import the component - it loads its own stylesheet:

tsx
import { Dialog } from '@zyncat/ui/dialog';

Usage

tsx
import { Dialog } from '@zyncat/ui/dialog';
 
<Dialog trigger={<Button variant="danger">Delete project</Button>} title="Delete project permanently?" tone="danger">
This action cannot be undone.
</Dialog>

Compose Dialog in your application. No Tailwind or external styling library is required; every value resolves from Zyncat UI's token vocabulary.

Dialog props

Dialog

PropTypeDefaultDescription
openboolean—Controlled open state. Omit for uncontrolled (use defaultOpen + trigger).
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open: boolean) => void—Fires whenever the open state changes. Pair with `open` for controlled use.
triggerReactElement | null—Optional element cloned to open the dialog (uncontrolled ergonomics).
activateOnActivateOn'click'Whether the trigger fires on `pointerdown` (snappier) or waits for `click`.
titleReactNode—Header title - rendered as the `<h2>` and wired to `aria-labelledby`.
descriptionReactNodenullSubtext under the title - wired to `aria-describedby`.
size'sm' | 'md' | 'lg''md'Panel width.
tone'default' | 'danger'—'danger' tints the header icon badge + is the convention for destructive confirms.
iconReactNode—Your own icon node for the header badge (alert dialogs).
dismissibleboolean—Close button + backdrop/Esc dismissal. Default true.
containerHTMLElement | null—Center inside this element instead of the viewport - it must be positioned (`position: relative` or similar). Scrim, scroll lock and inert scope to it; the rest of the page stays interactive.
footerReactNode | ((close: () => void) => ReactNode)—Action row - a node, or a render fn `(close) => node` so uncontrolled dialogs can dismiss.
childrenReactNode—Dialog body - scrolls when tall; its scroll edges flag the header lift + footer divider.
idstring—Base id for the panel; drives the trigger's `aria-controls` and the title/desc aria ids. Auto-generated when omitted.
...htmlAttributesHTMLAttributes<HTMLElement> & DataAttributes—Standard attributes (className, style, data-*, ...) forwarded to the dialog `<section>`.
animationDisableableAnimationopen 'slow'/'entrance', close 'base'/'standard'Open/close timing - motion tokens only, or `null` to disable.
Set in Geist & Newsreader — animated by the house engineZyncat UI · Rev 0.11 · MIT · Built by Tabsir Ahammed · Source on GitHub