Alert dialog
A modal that requires a choice, with no outside dismissal and no close button
import {
AlertDialog,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogTrigger,
} from "@nyte-ai/ui";The same component is exported unstyled from its own subpath, where AlertDialog is the full
namespace. Both paths export that name, so pick one per file.
import { AlertDialog } from "@nyte-ai/ui/alert-dialog";The Dialog surface with alert semantics. The two look identical, the behavior differs. Reach for it when the user has to answer the question before anything else happens.
The root exports give you the styled surface, trigger and close included. The subpath namespace
gives you every part unstyled, including Portal, Backdrop, and Viewport.
Usage
- Use it for a decision the user cannot back out of by clicking away. Delete, discard, overwrite, revoke.
- The footer needs an explicit way out, a Cancel
AlertDialogClose. There is no ✕ and outside press does nothing. - Title states the question, description states the consequence. Both are required.
- The destructive action is the last button and uses
variant="destructive". AlertDialogContentrenders the portal, backdrop, and popup as one unit. Use the namespace parts when you need to place them yourself or need a scrollableViewport.- To open it from a button that is not the trigger, control it with
openandonOpenChangeand drop the trigger.
Anatomy
<AlertDialog>
<AlertDialogTrigger />
<AlertDialogContent>
{/* Portal › Backdrop › Popup */}
<AlertDialogTitle />
<AlertDialogDescription />
<AlertDialogFooter>
<AlertDialogClose /> {/* cancel */}
<AlertDialogClose /> {/* confirm */}
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>The same tree with the unstyled namespace:
<AlertDialog.Root>
<AlertDialog.Trigger />
<AlertDialog.Portal>
<AlertDialog.Backdrop />
<AlertDialog.Viewport>
<AlertDialog.Popup>
<AlertDialog.Title />
<AlertDialog.Description />
<AlertDialog.Close />
</AlertDialog.Popup>
</AlertDialog.Viewport>
</AlertDialog.Portal>
</AlertDialog.Root>Examples
<AlertDialog>
<AlertDialogTrigger render={<Button variant="destructive" />}>Delete session</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogTitle>Delete this session?</AlertDialogTitle>
<AlertDialogDescription>
The history tree and every head under it are removed. This cannot be undone.
</AlertDialogDescription>
<AlertDialogFooter>
<AlertDialogClose render={<Button variant="ghost" />}>Cancel</AlertDialogClose>
<AlertDialogClose render={<Button variant="destructive" />}>Delete</AlertDialogClose>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>Opening it from somewhere else, a menu item or a keyboard shortcut, is a controlled dialog with no trigger.
const [open, setOpen] = useState(false);
<Button variant="destructive" onClick={() => setOpen(true)}>
Delete session
</Button>
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogContent>
<AlertDialogTitle>Delete this session?</AlertDialogTitle>
<AlertDialogDescription>This cannot be undone.</AlertDialogDescription>
<AlertDialogFooter>
<AlertDialogClose render={<Button variant="ghost" />}>Cancel</AlertDialogClose>
<AlertDialogClose render={<Button variant="destructive" />}>Delete</AlertDialogClose>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>;Props
| Export | Renders | Styling |
|---|---|---|
AlertDialog | Root | None, it renders no element |
AlertDialogTrigger | Trigger | None, pass render |
AlertDialogContent | Portal, Backdrop, and Popup | Styles land on the popup |
AlertDialogTitle | Title | Title type scale |
AlertDialogDescription | Description | Muted body type |
AlertDialogFooter | A <div> that right-aligns its buttons | Layout only |
AlertDialogClose | Close | None, pass render |
Every styled export accepts xstyle alongside className and style. The backdrop is not
exposed, change it with the scrim token, see Tokens.
The part tables below come from Base UI, MIT, © Material-UI SAS.
Root
Groups all parts of the alert 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: AlertDialog.Root.ChangeEventDetails) => void) | - | Event handler called when the alert dialog is opened or closed. |
| actionsRef | React.RefObject<AlertDialog.Root.Actions | null> | - | A ref to imperative actions. unmount: Manually unmounts the alert dialog.
Call this after any externally controlled closing animation finishes.close: Closes the alert dialog imperatively when called. |
| defaultTriggerId | string | null | - | ID of the trigger that the dialog is associated with.
This is useful in conjunction with the defaultOpen prop to create an initially open dialog. |
| handle | AlertDialog.Handle<Payload> | - | A handle to associate the alert dialog with a trigger. If specified, allows external triggers to control the alert dialog's open state. Can be created with the AlertDialog.createHandle() method. |
| 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.
This is useful in conjunction with the open prop to create a controlled dialog.
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.
This can be a regular React node or a render function that receives the payload of the active trigger. |
Trigger
A button that opens the alert dialog.
Renders a <button> element.
Trigger Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| handle | AlertDialog.Handle<Payload> | - | A handle to associate the trigger with an alert dialog. Can be created with the AlertDialog.createHandle() method. |
| nativeButton | boolean | true | Whether the component renders a native <button> element when replacing it
via the render prop.
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,
it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot triggerId prop). |
| className | string | ((state: AlertDialog.Trigger.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Trigger.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Trigger.State) => ReactElement) | - | Allows you to replace the component's HTML element
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 alert dialog is open. |
| data-disabled | - | Present when the trigger is disabled. |
Portal
A portal element that moves the popup to a different part of the DOM.
By default, the portal element is appended to <body>.
Renders a <div> element.
Portal Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| container | HTMLElement | ShadowRoot | React.RefObject<HTMLElement | ShadowRoot | null> | null | - | A parent element to render the portal element into. |
| className | string | ((state: AlertDialog.Portal.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Portal.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| keepMounted | boolean | false | Whether to keep the portal mounted in the DOM while the popup is hidden. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Portal.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Backdrop
An overlay displayed beneath the popup.
Renders a <div> element.
Backdrop Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| forceRender | boolean | false | Whether the backdrop is forced to render even when nested. |
| className | string | ((state: AlertDialog.Backdrop.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Backdrop.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Backdrop.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Backdrop Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-open | - | Present when the dialog is open. |
| data-closed | - | Present when the dialog is closed. |
| data-starting-style | - | Present when the dialog begins animating in. |
| data-ending-style | - | Present when the dialog is animating out. |
Viewport
A positioning container for the dialog popup that can be made scrollable.
Renders a <div> element.
Viewport Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: AlertDialog.Viewport.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Viewport.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Viewport.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Viewport 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
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.
By default, focus moves to the first tabbable element inside the popup, except when the dialog
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).
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).
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: AlertDialog.Popup.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Popup.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Popup.State) => ReactElement) | - | Allows you to replace the component's HTML element
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. |
Title
A heading that labels the dialog.
Renders an <h2> element.
Title Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: AlertDialog.Title.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Title.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Title.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Description
A paragraph with additional information about the dialog.
Renders a <p> element.
Description Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: AlertDialog.Description.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Description.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Description.State) => ReactElement) | - | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Close
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
via the render prop.
Set to false if the rendered element is not a button (for example, <div>). |
| className | string | ((state: AlertDialog.Close.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component's state. |
| style | React.CSSProperties | ((state: AlertDialog.Close.State) => React.CSSProperties | undefined) | - | Style applied to the element, or a function that returns a style object based on the component's state. |
| render | ReactElement | ((props: HTMLProps, state: AlertDialog.Close.State) => ReactElement) | - | Allows you to replace the component's HTML element
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
- The popup has
role="alertdialog", labelled byAlertDialogTitleand described byAlertDialogDescription. - Outside press does not close. Escape does. To block that, call
details.cancel()inonOpenChangewhendetails.reasonisescape-key. - Focus moves into the popup on open and returns to the trigger on close. Tab cycles inside the popup.
- Content outside the dialog is inert while it is open, and background scroll is locked.
initialFocusandfinalFocuson the popup override where focus lands.