Alert
A status banner — five intents (default and four status colors), an optional icon, and an optional dismiss button.
- Status
- Since
0.1.0- Accessibility pattern
- ARIA status region
Last updated
Install
Add Alert from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.
pnpm dlx shadcn@latest add @vegastack/alertThe same command installs the registry items it composes: @vegastack/icon-button.
Usage
import {
Alert,
AlertActions,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert";
<Alert intent="info">
<AlertTitle>Heads up</AlertTitle>
<AlertDescription>This is an informational alert.</AlertDescription>
</Alert>;Live announcements
Static alerts announce nothing. Set live when the banner is the RESULT of an action — a failed
save, a warning raised by what was just submitted — and a destructive or warning intent becomes
an assertive role="alert". Everything else, live or not, stays a polite role="status".
// static — rendered with the page, announces nothing
<Alert intent="info">
<AlertTitle>Two seats remain on this plan</AlertTitle>
</Alert>
// runtime — announced assertively the moment it mounts
<Alert intent="destructive" live>
<AlertTitle>Payment declined</AlertTitle>
<AlertDescription>Update the card on file and try again.</AlertDescription>
</Alert>Anatomy
Alert is a compound component. Compose the parts inside the root:
<Alert intent="success" dismissable onDismiss={handleDismiss}>
<AlertTitle>Title</AlertTitle>
<AlertDescription>Supporting description text.</AlertDescription>
<AlertActions>{/* action buttons */}</AlertActions>
</Alert>Alert— the client root banner (data-slot="alert"). Owns the intent, leading icon, live-region policy, and optional dismiss/self-dismiss behavior.AlertTitle— the bold leading line (data-slot="alert-title").AlertDescription— supporting body text (data-slot="alert-description").AlertActions— a row of action controls below the description (data-slot="alert-actions").
Examples
Variants
default, plus four semantic statuses — info, success, warning, destructive —
each with a matching leading icon and status color tokens (bg-X-subtle text-X-text border-X/20).
The strip layout variant is a compact single-line ribbon (icon + message + action, optional
dismiss). It is the base pattern for in-content notices and plan/trial rows — there is no separate
"inline banner" or "plan banner" component. For the full-width inverse strip across the top of a
page, use AnnouncementBanner instead.
Dismissable
Set dismissable to render a close button. Provide onDismiss to control visibility yourself, or
omit it to let the alert remove itself from the DOM.
Actions & controlled dismiss
Add an AlertActions row for follow-up controls, and pass onDismiss to drive visibility from your
own state instead of letting the alert self-remove. This is the recommended production path — it keeps
the alert in React's control so you can re-show it, log the dismissal, or coordinate other UI.
Icon options
Pass a custom leading icon (any lucide-react element) to override the intent's default, or set
hideIcon to drop the leading icon gutter entirely.
Variant matrix
Each intent rendered in its plain (icon-only) form and again with an AlertActions row, so the icon
gutter and action layout read consistently across every tone.
Strip variant
variant="strip" is the compact single-line info ribbon — centered icon + copy, tighter
padding — for settings banners and inline notices (distinct from the block alert).
Playground
Try every intent with the icon and dismiss options, then copy the generated JSX.
<Alert>
<AlertTitle>Heads up</AlertTitle>
<AlertDescription>Your trial ends in 7 days.</AlertDescription>
</Alert>API Reference
Alert
| Prop | Type | Default | Description |
|---|---|---|---|
dismissable | boolean | false | Render a dismiss (close) button in the top-right corner. |
dismissLabel | string | "Dismiss" | Accessible label for the dismiss button. |
hideIcon | boolean | false | Hide the leading icon entirely (overrides icon). |
icon | React.ReactNode | — | Custom leading icon. Falls back to the intent's default icon.
Pass a lucide-react icon element (e.g. <Bell />). |
intent | AlertIntent | "default" | Status intent — drives the color tokens and the default leading icon. |
live | boolean | false | Mark this alert as a runtime announcement — it appeared (or its copy changed) AFTER the page
had settled, in response to something the user did. Only then does an assertive
role="alert" become correct, and only for destructive/warning; every other intent stays
polite. Leave false for a statically rendered banner: a status region that is already in
the DOM at load announces nothing, so a page of three static alerts stays silent instead of
interrupting three times (D23, WAI-ARIA alert is for time-sensitive, important messages). |
onDismiss | (() => void) | — | Called when the dismiss button is clicked. When dismissable is set and no
handler is provided, the alert removes itself from the DOM internally. |
variant | "default" | "strip" | "default" | Layout — default block alert, or strip: the compact single-line info
ribbon (settings banners, inline notices). |
Data attributes and CSS variables on Alert
| Attribute | Values |
|---|---|
data-intent | mirrors a prop or state value |
data-live | "" |
data-slot | "alert" | "alert-content" | "alert-dismiss" | "alert-icon" |
data-variant | mirrors a prop or state value |
AlertTitle
AlertTitle adds no props of its own — it accepts everything the underlying element or Base UI primitive accepts (className, ref, ARIA attributes, event handlers).
Data attributes and CSS variables on AlertTitle
| Attribute | Values |
|---|---|
data-slot | "alert-title" |
AlertDescription
AlertDescription adds no props of its own — it accepts everything the underlying element or Base UI primitive accepts (className, ref, ARIA attributes, event handlers).
Data attributes and CSS variables on AlertDescription
| Attribute | Values |
|---|---|
data-slot | "alert-description" |
AlertActions
AlertActions adds no props of its own — it accepts everything the underlying element or Base UI primitive accepts (className, ref, ARIA attributes, event handlers).
Data attributes and CSS variables on AlertActions
| Attribute | Values |
|---|---|
data-slot | "alert-actions" |
Accessibility
- The root is a polite
role="status"region by default, for every intent. A live region that is already in the DOM when the page loads announces nothing, so a page carrying three static alerts stays silent instead of interrupting three times. - Pass
livefor a banner that appears (or re-words) in response to something the user did. Withlive, adestructiveorwarningintent escalates to the assertiverole="alert"— the only case WAI-ARIA reserves an interruption for; the other intents stay polite. - The leading icon is decorative (
aria-hidden); meaning is carried by the title and description text. - The dismiss button is a native
<button type="button">with an accessible label (dismissLabel, default"Dismiss"). - The dismiss button shows a
:focus-visiblering (outline-ring) — neveroutline: none.
| Key | Action |
|---|---|
| Tab | Move focus to the dismiss button (when dismissable). |
| Enter / Space | Activate the focused dismiss button. |
| Contract | States tested |
|---|---|
| Behaviour | default, error, open, saved, success |
| Accessibility | labeled, alert-announcement, semantic-html |
| Visual | default, hover, error, success |