Modal confirmation dialog for destructive or irreversible actions, with async-aware action handling and Cancel-focused defaults.
role="alertdialog" + aria-modal with initial focus pinned to Cancel for safer destructive flows
Async onAction with pending state, spinner, and stays open on rejection when onError is provided
Destructive tone variant switches the action accent to red
Surface-aware styling (pixel chrome vs. linear)
Scroll lock, focus trap, and Escape-to-close baked in
Status
stable
Category
overlays
Since
v1.8.0
API
import { PixelAlertDialog } from '@pxlkit/ui-kit';
Prop
Type
Default
Description
open* (required)
boolean
—
Whether the dialog is visible; set it from onOpenChange.
onOpenChange* (required)
(open: boolean) => void
—
Called with false when the dialog asks to close (Cancel, Escape, the backdrop, a completed action).
title* (required)
string
—
Title; it names the dialog.
description
string
—
Text under the title, wired via aria-describedby.
cancelLabel
string
'Cancel'
Label of the button that dismisses the dialog.
actionLabel
string
'Confirm'
Label of the button that confirms.
onAction* (required)
() => void | Promise<void>
—
The confirmed action. Its result matters: the dialog closes once it returns, or once the promise it returns resolves — and stays open, busy, until then.
onError
(error: unknown) => void
—
Called when onAction throws / rejects. Receives the thrown value. When set, the dialog stays OPEN on failure so the consumer can show an inline error. When unset, errors are silently swallowed (back-compat).
destructive
boolean
false
Red accent for a destructive action (cyan otherwise).
surface
'pixel' | 'linear'
—
Surface override; defaults to the nearest provider.
ref points to <div>.
Accessibility
WCAG target: 2.1 AA
alertdialog
Initial focus is placed on the Cancel button to prevent accidental confirmation of destructive actions.
Keyboard
Key
Action
When
Escape
Closes the dialog
not pending
Tab
Cycles focus inside the dialog
—
Enter
Activates the focused button
—
Usage
import { useState } from 'react';
import { PixelAlertDialog } from '@pxlkit/ui-kit';
export function Default() {
const [open, setOpen] = useState(false);
return (
<div>
<button type="button" onClick={() => setOpen(true)}>
Open alert dialog
</button>
<PixelAlertDialog
open={open}
onOpenChange={setOpen}
title="Save changes?"
description="Your edits will be applied to the live document."
actionLabel="Save"
onAction={() => setOpen(false)}
/>
</div>
);
}
Examples
Default
import { useState } from 'react';
import { PixelAlertDialog } from '@pxlkit/ui-kit';
export function Default() {
const [open, setOpen] = useState(false);
return (
<div>
<button type="button" onClick={() => setOpen(true)}>
Open alert dialog
</button>
<PixelAlertDialog
open={open}
onOpenChange={setOpen}
title="Save changes?"
description="Your edits will be applied to the live document."
actionLabel="Save"
onAction={() => setOpen(false)}
/>
</div>
);
}