{"slug":"dialog","name":"Dialog","packageName":"@liquidify/react","category":"presentational","maturity":"stable","summary":"A blocking, centered modal surface that interrupts the flow to present a title, an optional description or arbitrary body children, an optional accessory well (one small nested control), and a row of action buttons.","importPath":"@liquidify/react/dialog","sourcePath":"packages/@liquidify/react/src/components/dialog/dialog.tsx","specPath":"packages/@liquidify/react/src/components/dialog/spec.md","docsPath":"../liquidify-page/content/component-source/dialog.md","documentationStatus":"stable","storyIds":["presentational-dialog--default"],"additionalExports":["DialogAction","DialogActionRole","DialogSize","SizedPresentationalProps"],"anatomy":[{"name":"Modal.Header (.lq-dialog-header)","description":"Modal.Header (.lq-dialog-header) — the title, routed through the shared"},{"name":"Modal.Body (.lq-dialog-body)","description":"Modal.Body (.lq-dialog-body) — the description / body. When description"},{"name":".lq-dialog-accessory","description":".lq-dialog-accessory — an optional slot (children role: accessory) for"},{"name":"Modal.Footer (.lq-dialog-actions)","description":"Modal.Footer (.lq-dialog-actions) — the button row. data-layout=\"row\""}],"props":[{"name":"actions","type":"readonly DialogAction[]","required":true,"description":"The action buttons. Exactly two lay out side by side; otherwise stacked.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"children","type":"ReactNode","required":false,"description":"Arbitrary body content — the generic-Dialog superset over Alert's single-string `message`.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"className","type":"string | undefined","required":false,"description":"Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Uncontrolled seed for the open state (default `false`).","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"description","type":"string | undefined","required":false,"description":"Optional secondary description; the `aria-describedby` target.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"descriptionProps","type":"LabelProps | undefined","required":false,"description":"Per-instance typography override for the description (ADR-0028). Spread last.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"dismissible","type":"boolean | undefined","required":false,"description":"Whether Escape / a scrim tap dismiss the dialog (forwarded to Overlay). Defaults to `true`.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"labelProps","type":"LabelProps | undefined","required":false,"description":"Per-instance typography override for the title (ADR-0028). Spread last.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"material","type":"\"frosted\" | \"regular\" | \"clear\" | undefined","required":false,"description":"Material of the glass surface — `frosted · regular · clear` (§06). Forwarded to the engine, which resolves the chain `prop ?? <Material default> ?? \"regular\"`, so a bare surface inherits the enclosing provider default.","defaultValue":"enclosing `<Material default>`, else `\"regular\"`","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fires with the next open state on every close path (action, Escape, scrim).","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Passing it switches Dialog to controlled mode.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"perf","type":"\"low\" | \"high\" | undefined","required":false,"description":"Perf budget of the glass surface (ADR-0006/0007). Forwarded to the engine as `data-glass-perf`; `\"high\"` opts this surface into the edge-lensing filter. When omitted, derives from the enclosing `<Backdrop type>` (§04).","defaultValue":"derived from `<Backdrop type>`, else `\"low\"`","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"ref","type":"Ref<HTMLDivElement> | undefined","required":false,"description":"Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"size","type":"DialogSize | undefined","required":false,"description":"Card size — the `small · regular · large` subset of the canonical size scale (Dialog-only; Alert pins `small`).","defaultValue":"`\"regular\"`","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"},{"name":"title","type":"string","required":true,"description":"The dialog title — required; the `aria-labelledby` target.","declaredIn":"packages/@liquidify/react/src/components/dialog/dialog.tsx"}],"swiftUIMap":[{"swiftUI":"`isPresented: Binding<Bool>`","react":"`open` / `defaultOpen` / `onOpenChange`","notes":"presentation triad (ADR-0015), forwarded to `Overlay`; **open-state only**, not value-bearing. Controlled iff `open !== undefined` (§8); else `defaultOpen` (default `false`) seeds internal state.","relationship":"direct"},{"swiftUI":"`titleKey: Text` (the title)","react":"`title: string`","notes":"required; bold; the `aria-labelledby` target","relationship":"direct"},{"swiftUI":"`message: () -> Text`","react":"`description?: string` **or** body `children`","notes":"the `aria-describedby` target. Alert takes a single-string `message`; Dialog generalises the slot to arbitrary `children` (or a convenience `description` string).","relationship":"direct"},{"swiftUI":"`actions: () -> View` (Buttons)","react":"`actions: DialogAction[]`","notes":"`{ id, label, role?, onPress?, disabled? }`; each action carries a **stable, consumer-supplied `id`** — rows key by `id` (never `role+label`), duplicate labels are supported, a duplicate `id` or an empty collection is a dev-time error; activation runs `onPress` then closes","relationship":"direct"},{"swiftUI":"`Button.id` (collection identity)","react":"`DialogAction.id: string`","notes":"required; the React key + collection identity (§16.6)","relationship":"direct"},{"swiftUI":"`Button(role: .destructive)`","react":"`role: \"destructive\"`","notes":"red label (`--lq-color-action-destructive`), same hue in both schemes","relationship":"direct"},{"swiftUI":"`Button(role: .cancel)`","react":"`role: \"cancel\"`","notes":"the Escape / scrim-dismiss default; **neutral weight** (matches render — see States / open question, diverges from Alert's `bold`)","relationship":"direct"},{"swiftUI":"`Button(…).disabled(_:)`","react":"`disabled?: boolean`","notes":"native `disabled` on `<Button>`, no `aria-disabled`; hard-suppressed (no `onPress`, no close)","relationship":"direct"},{"swiftUI":"`actions: { TextField(…) }`","react":"`children` (accessory slot)","notes":"one small nested control above the footer (**children role: accessory**)","relationship":"direct"},{"swiftUI":"`.font(_:)` / `.foregroundStyle(_:)` on the title","react":"`labelProps?: LabelProps`","notes":"shared `Pick<TextProps,…>`; spread **last** over the computed title default (ADR-0028)","relationship":"direct"},{"swiftUI":"`.font(_:)` / `.foregroundStyle(_:)` on the message","react":"`descriptionProps?: LabelProps`","notes":"spread **last** over the `body`/`secondary` description default","relationship":"direct"},{"swiftUI":"(no SwiftUI analogue)","react":"`size?: DialogSize`","notes":"**Dialog-only** — maps the internal Modal width axis onto `SIZE_SCALE` (Alert pins `small`); default `regular`. See Sizes.","relationship":"web-only"},{"swiftUI":"(presentation chrome)","react":"`material?` / `perf?`","notes":"`PresentationalProps` — the card's glass surface; the base is tint-free (actions take the role palette)","relationship":"direct"},{"swiftUI":"(no SwiftUI analogue)","react":"`dismissible?: boolean`","notes":"gates the Escape / scrim-tap dismissal (Overlay), default `true`","relationship":"web-only"},{"swiftUI":"(no SwiftUI analogue)","react":"`ref?: Ref<HTMLDivElement>`","notes":"forwarded to the documented semantic root — the dialog card (Modal's glass `<div role=\"dialog\">`); attached while open, `null` while closed","relationship":"web-only"}],"tokens":["--lq-color-action-destructive","--lq-color-label-primary-","--lq-color-label-secondary-","--lq-dialog-control-fill","--lq-dialog-pad","--lq-dialog-w-small","--lq-duration-","--lq-easing-","--lq-glass-","--lq-motion-hover-scale","--lq-overlay-scrim-opacity","--lq-radius-pill","--lq-shadow-presentational","--lq-space-12","--lq-space-16","--lq-space-20","--lq-space-8"],"keyboard":[{"key":"Keyboard","action":"Keyboard (via Overlay): Escape dismisses (when dismissible); Tab / Shift+Tab are trapped, cycling the focusable accessory + actions in DOM order, wrapping at the ring edges; Enter/Space on a focused action activates it (native ); focus returns to the invoking element on close."}],"variants":[],"variantPages":[]}