Alert
An alert is a message that stays in the page, next to what it is about.
Each variant is a 10% tint and a 30% border of its hue under
text-foreground, so a brand only sets --success, --warning and
--destructive for alerts to follow.
import Alert from '@zuilib/components/alert'
Variants
info tints from --primary (--info is a surface token, not a hue);
neutral is the muted surface. Each has a default status icon, painted in
the variant colour.
Icon and actions
icon replaces the default glyph; false removes the icon column.
Alert.Actions is a row for buttons under the text.
Dismissible
dismissible adds a close button named Dismiss, <title>. Uncontrolled,
a click removes the alert (remount with a new key to show it again).
With open, the click only calls onDismiss and the parent decides.
Props
AlertProps extends div props (minus title).
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'info' | 'success' | 'warning' | 'destructive' | 'neutral' | 'info' | |
icon | ReactNode | false | variant icon | false or null removes the icon column; decorative (aria-hidden) |
live | 'assertive' | 'polite' | 'off' | 'assertive' | assertive is role="alert"; polite is role="status" for info / success / neutral (warning and destructive stay alert); off renders no live role. An explicit role prop wins |
dismissible | boolean | false | Renders the close button |
onDismiss | () => void | — | Called when the close button is pressed |
open | boolean | — | Controlled visibility; when given the close button only calls onDismiss |
dismissLabel | string | 'Dismiss' | Close button name, composed with the Alert.Title text |
className | string | — | Merged last, after the variant classes |
Alert.Title, Alert.Description and Alert.Actions take div props.
The title is a div, not a heading; pass role="heading" aria-level={n}
when it belongs in the outline. Its id (generated unless you pass one) is
what the close button's name refers to.
Slots
| Slot | Element | Notes |
|---|---|---|
[data-slot="alert"] | div | Root. Also data-variant, data-live, data-dismissible |
[data-slot="alert-icon"] | span | Icon column; aria-hidden |
[data-slot="alert-content"] | div | Column holding the children |
[data-slot="alert-title"] | div | — |
[data-slot="alert-description"] | div | Links inside are underlined |
[data-slot="alert-actions"] | div | Flex row, wraps |
[data-slot="alert-close"] | button | Present when dismissible |
[data-slot="alert-close-icon"] | svg | — |
/* Consumer CSS: informational alerts in a hue of your own */
[data-slot="alert"][data-variant="info"] {
background-color: color-mix(in oklch, var(--brand-blue) 10%, transparent);
border-color: color-mix(in oklch, var(--brand-blue) 30%, transparent);
}
Tokens
| Token | Used for |
|---|---|
--primary, --success, --warning, --destructive | Tint and border per variant |
--success-text, --warning-text | Icon colour where the base hue is too light on the tint |
--muted, --border, --muted-foreground | The neutral surface and icon |
--foreground | Title and description text |
--radius-lg | Corner radius |
--ring | Close button focus ring |
Accessibility
role="alert"by default (screen readers interrupt);live="polite"downgrades non-urgent variants torole="status";live="off"for a callout that is part of the page on load.- The icon is decorative;
Alert.Titlecarries the meaning. - The close button is named
"{dismissLabel}, {title}"througharia-labelledby, so several alerts' close buttons are distinguishable. - When the alert disappears while focus is inside it, focus moves to the element it came from, else the next tabbable element after the alert, then the previous one, then a focusable ancestor. It never lands on
<body>. - Description text keeps full
--foregroundcolour:--muted-foregroundsits under 4.5:1 on the tints.