ComponentsUpdated Sep 9, 2026
Dialog
A modal window. Content bundles the portal, backdrop, popup, and close button; Header, Body, and Footer lay out the inside. Trigger and Close are Buttons, so they take the same variants.
Import
Source: packages/ui/src/components/dialog
tsx
import { Dialog } from '@highlight/ui'tsx
import { Dialog } from '@highlight/ui'
export default function DialogBasic() {
return (
<Dialog>
<Dialog.Trigger>View notifications</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Notifications</Dialog.Title>
<Dialog.Description>You are all caught up.</Dialog.Description>
</Dialog.Header>
<Dialog.Body>
<p className="text-foreground/70 text-sm">Every notification has been reviewed. New ones will appear here.</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.Close>Done</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog>
)
}Controlled
open and onOpenChange, with the trigger elsewhere.
tsx
import { useState } from 'react'
import { Button, Dialog } from '@highlight/ui'
export default function DialogControlled() {
const [open, setOpen] = useState(false)
return (
<div className="flex items-center gap-3">
<Button variant="secondary" onClick={() => setOpen(true)}>
Open from outside
</Button>
<Dialog open={open} onOpenChange={setOpen}>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Controlled</Dialog.Title>
<Dialog.Description>Open state lives in React.</Dialog.Description>
</Dialog.Header>
<Dialog.Footer>
<Button variant="secondary" onClick={() => setOpen(false)}>
Close programmatically
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog>
</div>
)
}Destructive and blocking
showClose hides the corner button; disableEscape keeps Escape and the backdrop from closing.
tsx
import { Dialog } from '@highlight/ui'
export default function DialogVariants() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<Dialog>
<Dialog.Trigger variant="danger">Delete thread</Dialog.Trigger>
<Dialog.Content showClose={false}>
<Dialog.Header>
<Dialog.Title>Delete this thread?</Dialog.Title>
<Dialog.Description>Messages and attachments are removed for everyone.</Dialog.Description>
</Dialog.Header>
<Dialog.Footer>
<Dialog.Close variant="secondary">Cancel</Dialog.Close>
<Dialog.Close variant="danger">Delete</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog>
<Dialog disableEscape>
<Dialog.Trigger variant="bold">Finish setup</Dialog.Trigger>
<Dialog.Content showClose={false}>
<Dialog.Header>
<Dialog.Title>One more step</Dialog.Title>
<Dialog.Description>Escape and the backdrop are disabled; pick an action to continue.</Dialog.Description>
</Dialog.Header>
<Dialog.Footer>
<Dialog.Close variant="secondary">Later</Dialog.Close>
<Dialog.Close variant="primary">Connect calendar</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog>
</div>
)
}Open from a text link
tsx
import { Dialog } from '@highlight/ui'
export default function DialogCustomTrigger() {
return (
<Dialog>
<Dialog.Trigger
nativeButton={false}
render={
<span className="text-foreground/70 hover:text-foreground cursor-pointer text-sm underline underline-offset-4">
Open from a text link
</span>
}
/>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Custom trigger</Dialog.Title>
<Dialog.Description>
Pass render to make any element the trigger. Set nativeButton to false when it is not a button.
</Dialog.Description>
</Dialog.Header>
</Dialog.Content>
</Dialog>
)
}Parts
Compound sub-components. Every part accepts className and forwards the rest of its props to Base UI.
Dialog.Trigger- A Button that opens the dialog. Takes variant, size, shape, or a render element.
Dialog.Content- Portal + Backdrop + Popup + close button. showClose, backdropClassName, initialFocus.
Dialog.Header / Body / Footer- Layout slots. Body scrolls when content overflows.
Dialog.Title / Description- Accessible name and description.
Dialog.Close- A Button that closes the dialog.
Dialog.Portal / Backdrop / Popup- Low-level parts when Content is not enough.
Props
Props added on top of the underlying element or Base UI part.
| Prop | Type | Default | Description |
|---|---|---|---|
disableEscape | boolean | false | Only explicit Close clicks dismiss the dialog. |