ComponentsUpdated Sep 9, 2026
Alert Dialog
A dialog that demands a decision. Same parts as Dialog, but it cannot be dismissed by clicking outside, and it uses the alertdialog role.
Import
Source: packages/ui/src/components/alert-dialog
tsx
import { AlertDialog } from '@highlight/ui'Basic
Cancel first, destructive action last.
tsx
import { AlertDialog } from '@highlight/ui'
export default function AlertDialogBasic() {
return (
<AlertDialog>
<AlertDialog.Trigger variant="danger">Delete account</AlertDialog.Trigger>
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>Delete your account?</AlertDialog.Title>
<AlertDialog.Description>
This cannot be undone. Your meetings, notes, and integrations are permanently removed.
</AlertDialog.Description>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Close variant="secondary">Cancel</AlertDialog.Close>
<AlertDialog.Close variant="danger">Delete account</AlertDialog.Close>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog>
)
}Guarding unsaved changes
Intercept onOpenChange on a Dialog and raise an AlertDialog instead of closing.
tsx
import { useState } from 'react'
import { AlertDialog, Button, Dialog } from '@highlight/ui'
export default function AlertDialogConfirmClose() {
const [dialogOpen, setDialogOpen] = useState(false)
const [confirmOpen, setConfirmOpen] = useState(false)
const [draft, setDraft] = useState('')
return (
<>
<Dialog
open={dialogOpen}
onOpenChange={(open) => {
if (!open && draft) {
setConfirmOpen(true)
return
}
setDraft('')
setDialogOpen(open)
}}
>
<Dialog.Trigger>Compose note</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>New note</Dialog.Title>
<Dialog.Description>Closing with unsaved text asks first.</Dialog.Description>
</Dialog.Header>
<Dialog.Body>
<textarea
value={draft}
onChange={(event) => setDraft(event.target.value)}
placeholder="Type something, then close…"
className="border-border/20 bg-background text-foreground focus-visible:border-border/40 min-h-28 w-full rounded-lg border px-3 py-2 text-sm outline-none"
/>
</Dialog.Body>
</Dialog.Content>
</Dialog>
<AlertDialog open={confirmOpen} onOpenChange={setConfirmOpen}>
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>Discard note?</AlertDialog.Title>
<AlertDialog.Description>Your text will be lost.</AlertDialog.Description>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Close>Keep editing</AlertDialog.Close>
<Button
variant="danger"
onClick={() => {
setConfirmOpen(false)
setDraft('')
setDialogOpen(false)
}}
>
Discard
</Button>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog>
</>
)
}Parts
Compound sub-components. Every part accepts className and forwards the rest of its props to Base UI.
AlertDialog.Trigger / Close- Buttons; take variant, size, shape.
AlertDialog.Content- Portal + Backdrop + Popup. showClose defaults to true.
AlertDialog.Header / Body / Footer / Title / Description- Same as Dialog.