first commit
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# AlertDialog
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs --> - alert-dialog.variants — `alertDialogOverlayVariants…
|
||||
- [alert-dialog.variants](./alert-dialog.variants.md) — `alertDialogOverlayVariants`, `alertDialogContentVariants`, `alertDialogHeaderVariants`, `alertDialogFooterVariants`, `…
|
||||
- alert-dialog.variants — `alertDialogOverlayVariants…
|
||||
|
||||
- [alert-dialog.variants](./alert-dialog.variants.md) — `alertDialogOverlayVariants`, `alertDialogContentVariants`, `alertDialogHeaderVariants`, `alertDialogFooterVariants`, `…
|
||||
|
||||
- alert-dialog.variants — `alertDialogOverlayVariants…
|
||||
|
||||
- [alert-dialog.variants](./alert-dialog.variants.md) — `alertDialogOverlayVariants`, `alertDialogContentVariants`, `alertDialogHeaderVariants`, `alertDialogFooterVariants`, `…
|
||||
|
||||
- alert-dialog.variants — `alertDialogOverlayVariants…
|
||||
|
||||
- [alert-dialog.variants](./alert-dialog.variants.md) — `alertDialogOverlayVariants`, `alertDialogContentVariants`, `alertDialogHeaderVariants`, `alertDialogFooterVariants`, `…
|
||||
- [alert-dialog.variants](./alert-dialog.variants.md) — `alertDialogOverlayVariants`, `alertDialogContentVariants`, `alertDialogHeaderVariants`, `alertDialogFooterVariants`, `…
|
||||
|
||||
## Purpose
|
||||
|
||||
`<AlertDialog>` and its sub-components (`<AlertDialogTrigger>`, `<AlertDialogPortal>`, `<AlertDialogOverlay>`, `<AlertDialogContent>`, `<AlertDialogHeader>`, `<AlertDialogFooter>`, `<AlertDialogTitle>`, `<AlertDialogDescription>`, `<AlertDialogAction>`, `<AlertDialogCancel>`) are the chassis modal CONFIRMATION dialog primitives built on `@radix-ui/react-alert-dialog`.
|
||||
|
||||
The structural difference between `<AlertDialog>` and `<Dialog>` is the click-outside-suppression: an alert dialog CANNOT be dismissed by clicking the overlay backdrop — the user MUST press the `<AlertDialogAction>` or `<AlertDialogCancel>` button. Use `<AlertDialog>` for destructive operations (delete / discard / log out) where an accidental backdrop click could lose work; use `<Dialog>` for everything else.
|
||||
|
||||
Per the WAI-ARIA alertdialog pattern, every alert dialog MUST contain an `<AlertDialogTitle>` so the accessible name is announced. Use `className="sr-only"` if the visible UI does not need a heading. Radix renders `role="alertdialog"` (NOT `role="dialog"`) so screen readers know to announce the prompt as a high-priority interrupt.
|
||||
|
||||
## Features
|
||||
|
||||
- `role="alertdialog"` (Radix-managed) so screen readers announce a high-priority prompt.
|
||||
- Click-outside dismissal SUPPRESSED — only Action / Cancel resolve the dialog.
|
||||
- Escape closes (treated as cancel) — Radix-managed.
|
||||
- Focus-trap on open; restore-focus to the trigger on close.
|
||||
- Four content sizes (`sm`, `default`, `lg`, `xl`) scale the panel max-width.
|
||||
- `<AlertDialogAction>` defaults to Button `variant="default"` styling (primary).
|
||||
- `<AlertDialogCancel>` defaults to Button `variant="outline"` styling (secondary).
|
||||
- Theme-driven cva overrides for every slot via `useThemedVariants("AlertDialog<Slot>")`.
|
||||
- All sub-components forward refs.
|
||||
- `motion-reduce:animate-none` collapses animations under `prefers-reduced-motion: reduce`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```tsx
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@suaveplan/react-ui";
|
||||
|
||||
export function ConfirmDelete() {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger>Delete account</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction>Delete</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```tsx
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@suaveplan/react-ui";
|
||||
import { useState } from "react";
|
||||
|
||||
export function ConfirmDestructive({
|
||||
title,
|
||||
description,
|
||||
onConfirm,
|
||||
}: {
|
||||
readonly title: string;
|
||||
readonly description: string;
|
||||
readonly onConfirm: () => Promise<void>;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [busy, setBusy] = useState(false);
|
||||
|
||||
async function handleConfirm() {
|
||||
setBusy(true);
|
||||
try {
|
||||
await onConfirm();
|
||||
setOpen(false);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<AlertDialog open={open} onOpenChange={setOpen}>
|
||||
<AlertDialogContent size="sm">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{title}</AlertDialogTitle>
|
||||
<AlertDialogDescription>{description}</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={busy}>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={handleConfirm} disabled={busy}>
|
||||
{busy ? "Working…" : "Confirm"}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `<AlertDialog>`
|
||||
|
||||
Wraps the Radix AlertDialog Root. Same lifecycle props as `<Dialog>` (`open`, `defaultOpen`, `onOpenChange`).
|
||||
|
||||
### `<AlertDialogContent>`
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `size` | `"sm" \| "default" \| "lg" \| "xl"` | `"default"` | Visual variant scaling the panel max-width. |
|
||||
|
||||
### `<AlertDialogTitle>`
|
||||
|
||||
REQUIRED for accessibility. Render `className="sr-only"` if no visible heading is needed.
|
||||
|
||||
### `<AlertDialogAction>`, `<AlertDialogCancel>`
|
||||
|
||||
Renders as buttons with the default Button `variant="default"` and `variant="outline"` styling respectively. Activating either resolves the dialog (closes it).
|
||||
|
||||
### `<AlertDialogTrigger>`, `<AlertDialogPortal>`, `<AlertDialogOverlay>`, `<AlertDialogHeader>`, `<AlertDialogFooter>`, `<AlertDialogDescription>`
|
||||
|
||||
Direct re-exports of the Radix sub-components with the chassis cva applied.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The chassis NEVER assigns a numeric `z-index` — Radix portals handle stacking.
|
||||
- The Action / Cancel button cva is INLINED into AlertDialog rather than reusing `<Button>` so an ejected source copy stays self-contained (matches the shadcn upstream `alert-dialog` recipe).
|
||||
- `<AlertDialogContent>` self-portals via `<AlertDialogPortal>` so consumers do not need to compose the portal manually.
|
||||
- The Cancel button uses `mt-2 sm:mt-0` so it stacks beneath the Action on small screens (Action becomes the visually emphasised primary-end position) and aligns horizontally above `sm`.
|
||||
- Radix's a11y warning fires when no `<AlertDialogDescription>` is provided either — the chassis does not enforce this since some single-line confirmations only need a title; consumers can pass `aria-describedby={undefined}` on `<AlertDialogContent>` if they want to suppress the warning explicitly.
|
||||
Reference in New Issue
Block a user