# Dialog (/cloud/primitives/dialog)



```ts title="Import"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@nyte-ai/ui";
import { Dialog as DialogPrimitive } from "@nyte-ai/ui/dialog";
```

Implemented in `packages/ui/src/components/ui/dialog.tsx`, wrapping
[`@nyte-ai/ui/dialog`](/cloud/headless/dialog). `Dialog` is `Dialog.Root` re-exported. The
wrapper does not export a styled Trigger or Close; use `DialogPrimitive.Trigger` and
`DialogPrimitive.Close` with `render={<Button … />}`.

## Usage [#usage]

* Every dialog **must** have a `DialogTitle`. It becomes the accessible name. If the title is
  visually redundant, hide it with your own visually-hidden style rather than omitting it.
* Use `DialogDescription` for the one sentence that explains the consequence. Longer content goes
  in the body.
* Confirmations that destroy something use [Alert dialog](/cloud/primitives/alert-dialog), which
  does not dismiss on outside press.
* `showCloseButton` is on by default. Turn it off only when the footer already has a Cancel and the
  dialog is small enough that the ✕ would crowd the title.

## Anatomy [#anatomy]

```tsx
<Dialog>
  <DialogPrimitive.Trigger />
  <DialogContent>
    {/* Portal › Backdrop › Popup, plus Close */}
    <DialogHeader>
      <DialogTitle />
      <DialogDescription />
    </DialogHeader>
    …
    <DialogFooter />
  </DialogContent>
</Dialog>
```

`DialogContent` renders `Dialog.Portal › Dialog.Backdrop › Dialog.Popup` and, when
`showCloseButton`, a `Dialog.Close` rendered as `<Button size="icon-sm" variant="ghost">` with
`aria-label="Close"` in the top-right corner. `DialogHeader` reserves `--nyte-control-height-sm` of
right padding so the title clears that button.

## Example [#example]

<Preview>
  <DialogDemo />
</Preview>

```tsx
<Dialog>
  <DialogPrimitive.Trigger render={<Button variant="outline" />}>
    Rename session
  </DialogPrimitive.Trigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Rename session</DialogTitle>
      <DialogDescription>The name shows in the sidebar and in the window title.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogPrimitive.Close render={<Button variant="ghost" />}>Cancel</DialogPrimitive.Close>
      <DialogPrimitive.Close render={<Button />}>Save</DialogPrimitive.Close>
    </DialogFooter>
  </DialogContent>
</Dialog>
```

## Props [#props]

### Dialog (Root) [#dialog-root]

Groups all parts of the dialog.
Doesn't render its own HTML element.

**Root Props:**

| Prop                    | Type                                                                      | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| :---------------------- | :------------------------------------------------------------------------ | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaultOpen             | `boolean`                                                                 | `false` | Whether the dialog is initially open. To render a controlled dialog, use the `open` prop instead.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| open                    | `boolean`                                                                 | -       | Whether the dialog is currently open.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| onOpenChange            | `((open: boolean, eventDetails: Dialog.Root.ChangeEventDetails) => void)` | -       | Event handler called when the dialog is opened or closed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| actionsRef              | `React.RefObject<Dialog.Root.Actions \| null>`                            | -       | A ref to imperative actions. `unmount`: Manually unmounts the dialog.&#xA;Call this after any externally controlled closing animation finishes.`close`: Closes the dialog imperatively when called.                                                                                                                                                                                                                                                                                                                                                                                           |
| defaultTriggerId        | `string \| null`                                                          | -       | ID of the trigger that the dialog is associated with.&#xA;This is useful in conjunction with the `defaultOpen` prop to create an initially open dialog.                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| disablePointerDismissal | `boolean`                                                                 | `false` | Whether to prevent the dialog from closing on outside presses.&#xA;For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it.                                                                                                                                                                                                                                                                                                                                                                                                                          |
| handle                  | `Dialog.Handle<Payload>`                                                  | -       | A handle to associate the dialog with a trigger.&#xA;If specified, allows external triggers to control the dialog's open state.&#xA;Can be created with the Dialog.createHandle() method.                                                                                                                                                                                                                                                                                                                                                                                                     |
| modal                   | `boolean \| 'trap-focus'`                                                 | `true`  | Determines if the dialog enters a modal state when open. `true`: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled.`false`: user interaction with the rest of the document is allowed.`'trap-focus'`: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled. When `modal` is `true` or `'trap-focus'`, render `<Dialog.Close>` inside `<Dialog.Popup>` so&#xA;touch screen readers can escape the popup. |
| onOpenChangeComplete    | `((open: boolean) => void)`                                               | -       | Event handler called after any animations complete when the dialog is opened or closed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| triggerId               | `string \| null`                                                          | -       | ID of the trigger that the dialog is associated with.&#xA;This is useful in conjunction with the `open` prop to create a controlled dialog.&#xA;There's no need to specify this prop when the dialog is uncontrolled (that is, when the `open` prop is not set).                                                                                                                                                                                                                                                                                                                              |
| children                | `React.ReactNode \| PayloadChildRenderFunction<Payload>`                  | -       | The content of the dialog.&#xA;This can be a regular React node or a render function that receives the `payload` of the active trigger.                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

### DialogContent [#dialogcontent]

`DialogContentProps` is `StyledProps<Dialog.Popup.Props>` plus:

| Prop              | Type      | Default | Description                                        |
| ----------------- | --------- | ------- | -------------------------------------------------- |
| `showCloseButton` | `boolean` | `true`  | Render the ✕ close button in the top-right corner. |

The styling channels (`className`, `style`, `xstyle`) apply to the Popup. The Backdrop is not
exposed; theme `--nyte-color-scrim` to change it.

A container for the dialog contents.
Renders a `<div>` element.

**Popup Props:**

| Prop         | Type                                                                                                                          | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| :----------- | :---------------------------------------------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| initialFocus | `boolean \| React.RefObject<HTMLElement \| null> \| ((openType: InteractionType) => boolean \| void \| HTMLElement \| null)`  | -       | Determines the element to focus when the dialog is opened.&#xA;By default, focus moves to the first tabbable element inside the popup, except when the dialog&#xA;is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard. `false`: Do not move focus.`true`: Move focus based on the default behavior (first tabbable element or popup).`RefObject`: Move focus to the ref element.`function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).&#xA;Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing. |
| finalFocus   | `boolean \| React.RefObject<HTMLElement \| null> \| ((closeType: InteractionType) => boolean \| void \| HTMLElement \| null)` | -       | Determines the element to focus when the dialog is closed. `false`: Do not move focus.`true`: Move focus based on the default behavior (trigger or previously focused element).`RefObject`: Move focus to the ref element.`function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).&#xA;Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.                                                                                                                                                                                               |
| className    | `string \| ((state: Dialog.Popup.State) => string \| undefined)`                                                              | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| style        | `React.CSSProperties \| ((state: Dialog.Popup.State) => React.CSSProperties \| undefined)`                                    | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| render       | `ReactElement \| ((props: HTMLProps, state: Dialog.Popup.State) => ReactElement)`                                             | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |

**Popup Data Attributes:**

| Attribute               | Type | Description                                                      |
| :---------------------- | :--- | :--------------------------------------------------------------- |
| data-open               | -    | Present when the dialog is open.                                 |
| data-closed             | -    | Present when the dialog is closed.                               |
| data-nested             | -    | Present when the dialog is nested within another dialog.         |
| data-nested-dialog-open | -    | Present when the dialog has other open dialogs nested within it. |
| data-starting-style     | -    | Present when the dialog begins animating in.                     |
| data-ending-style       | -    | Present when the dialog is animating out.                        |

**Popup CSS Variables:**

| Variable           | Type     | Description                                   |
| :----------------- | :------- | :-------------------------------------------- |
| `--nested-dialogs` | `number` | Indicates how many dialogs are nested within. |

### DialogTitle [#dialogtitle]

A heading that labels the dialog.
Renders an `<h2>` element.

**Title Props:**

| Prop      | Type                                                                                       | Default | Description                                                                                                                                                                                   |
| :-------- | :----------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| className | `string \| ((state: Dialog.Title.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style     | `React.CSSProperties \| ((state: Dialog.Title.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| render    | `ReactElement \| ((props: HTMLProps, state: Dialog.Title.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### DialogDescription [#dialogdescription]

A paragraph with additional information about the dialog.
Renders a `<p>` element.

**Description Props:**

| Prop      | Type                                                                                             | Default | Description                                                                                                                                                                                   |
| :-------- | :----------------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| className | `string \| ((state: Dialog.Description.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style     | `React.CSSProperties \| ((state: Dialog.Description.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| render    | `ReactElement \| ((props: HTMLProps, state: Dialog.Description.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### DialogHeader, DialogFooter [#dialogheader-dialogfooter]

Plain `<div>`s with `StyledProps<React.ComponentProps<"div">>`. Header is a column with
`--nyte-space-1` gap; footer is a right-aligned row with `--nyte-space-2` gap.

### Trigger and Close [#trigger-and-close]

From `@nyte-ai/ui/dialog`:

A button that opens the dialog.
Renders a `<button>` element.

**Trigger Props:**

| Prop         | Type                                                                                         | Default | Description                                                                                                                                                                                             |
| :----------- | :------------------------------------------------------------------------------------------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| handle       | `Dialog.Handle<Payload>`                                                                     | -       | A handle to associate the trigger with a dialog.&#xA;Can be created with the Dialog.createHandle() method.                                                                                              |
| nativeButton | `boolean`                                                                                    | `true`  | Whether the component renders a native `<button>` element when replacing it&#xA;via the `render` prop.&#xA;Set to `false` if the rendered element is not a button (for example, `<div>`).               |
| payload      | `Payload`                                                                                    | -       | A payload to pass to the dialog when it is opened.                                                                                                                                                      |
| id           | `string`                                                                                     | -       | ID of the trigger. In addition to being forwarded to the rendered element,&#xA;it is also used to specify the active trigger for the dialog in controlled mode (with the Dialog.Root `triggerId` prop). |
| className    | `string \| ((state: Dialog.Trigger.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                                |
| style        | `React.CSSProperties \| ((state: Dialog.Trigger.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                             |
| render       | `ReactElement \| ((props: HTMLProps, state: Dialog.Trigger.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.           |

**Trigger Data Attributes:**

| Attribute       | Type | Description                                    |
| :-------------- | :--- | :--------------------------------------------- |
| data-popup-open | -    | Present when the corresponding dialog is open. |
| data-disabled   | -    | Present when the trigger is disabled.          |

A button that closes the dialog.
Renders a `<button>` element.

**Close Props:**

| Prop         | Type                                                                                       | Default | Description                                                                                                                                                                                   |
| :----------- | :----------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| nativeButton | `boolean`                                                                                  | `true`  | Whether the component renders a native `<button>` element when replacing it&#xA;via the `render` prop.&#xA;Set to `false` if the rendered element is not a button (for example, `<div>`).     |
| className    | `string \| ((state: Dialog.Close.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style        | `React.CSSProperties \| ((state: Dialog.Close.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| render       | `ReactElement \| ((props: HTMLProps, state: Dialog.Close.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

**Close Data Attributes:**

| Attribute     | Type | Description                          |
| :------------ | :--- | :----------------------------------- |
| data-disabled | -    | Present when the button is disabled. |

## Accessibility [#accessibility]

Base UI's dialog behavior, unchanged by the wrapper:

* The popup has `role="dialog"` and `aria-modal="true"`, and is labelled by `DialogTitle` and
  described by `DialogDescription` automatically.
* Focus moves into the popup on open (first tabbable element, or the popup itself when opened by
  touch) and returns to the trigger on close. Tab cycles inside the popup.
* Escape closes. Outside press closes unless `disablePointerDismissal` is set on Root.
* Content outside the dialog is inert while it is open, and background scroll is locked.

## Styling [#styling]

| Token                                                                     | Role                                                                                               |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `--nyte-layer-dialog`                                                     | z-index of backdrop and popup (50)                                                                 |
| `--nyte-color-scrim`                                                      | Backdrop                                                                                           |
| `--nyte-dialog-width`, `-max-width`, `-max-height`                        | Popup box                                                                                          |
| `--nyte-radius-dialog`, `--nyte-elevation-dialog`, `--nyte-color-popover` | Popup surface                                                                                      |
| `--nyte-space-4`                                                          | Popup padding and grid gap                                                                         |
| `--nyte-font-size-title` / `--nyte-leading-title`                         | Title                                                                                              |
| `--nyte-color-muted-foreground`                                           | Description                                                                                        |
| `--nyte-motion-normal`                                                    | Fade and 0.98 scale via `[data-starting-style]` / `[data-ending-style]`; `0s` under reduced motion |

`dialogStyles` is exported so Alert dialog renders the same surface.
