Alert
Displays a callout for user attention — five semantic variants, an optional icon, a title, a description, and an action.
- Status
- Since
0.1.0- Accessibility pattern
- role status, alert only when live, icon beside the label
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Alert before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify alertInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/alertRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
Usage
import {
Alert,
AlertAction,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert";
<Alert>
<InfoIcon />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components and dependencies to your app using the CLI.
</AlertDescription>
</Alert>;Anatomy
Examples
Composition
An icon, then AlertTitle, then AlertDescription, then AlertAction. The icon is a direct child
of Alert — the recipe reserves a column for it and spans it across both rows, so nothing has to
be wrapped.
Basic
A basic alert with an icon, a title and a description.
Destructive
Use variant="destructive" for a failure the user has to act on.
Status
Ours: success, warning and info complete the four chromatic families (COL-12), each written
in upstream's destructive shape — the family's -text ink on the card surface, with the
description one step dimmer. Give every one of them an icon, so the hue is never the only signal.
Action
Use AlertAction to add a button or another action element to the alert. It is positioned on the
trailing edge of the first row, and the root reserves the inline space for it. Use a
Button size="xs" variant="outline" — the Regent app's "Try again" on a failed refresh.
When you move focus to an alert (after a failed submit, say), it shows no focus ring: it is a
programmatic focus target, not a control, so give it tabIndex={-1} and keep the ring for the
action button inside it.
Custom Colors
You can retint an alert by passing classes through className. Upstream's example reaches for the
raw Tailwind palette; use semantic tokens instead, so the override follows the theme into dark mode
and survives a retheme.
RTL
The root is written in logical properties — text-start, and a grid whose action column is the
trailing one — so a right-to-left document mirrors without any extra work.
Live alerts
An Alert is a polite role="status" region by default, whatever its variant, so an alert that is
on the page when it loads is read in page order and interrupts nobody (A11Y-3). Pass live when
the alert appears after mount because of something the user just did — a failed save, a declined
card. With live, a destructive or warning alert becomes an assertive role="alert"; every
other variant stays a polite status.
To leave an alert out of every live region — a standing notice that is part of the page when it
loads — pass your own role, which always wins: role="note" makes it a static note
that no screen reader announces on its own. live stays off by default, so nothing changes for an
alert that does not pass one.
Action placement
AlertAction takes its own column beside the title and description, top-aligned with the title, so
a long label never reaches under the text (LAY-15). When the alert itself is narrower than 28rem —
a phone, a sidebar card — the action drops below the text instead. The switch follows the alert's
own width (a container query), not the viewport's.
Two actions
Place two buttons straight inside AlertAction; it lays them out in a row with a gap-2 gap and
wraps them onto a second line when the alert is too narrow to hold both. There is no need for a
ButtonGroup or a wrapper div. Lead with the primary action and keep both the same size.
Status surfaces
Each status variant tints its own border (30%) and background (5%, 10% in dark); default keeps
the neutral border and card. An outline button inside a status alert wears the variant colour at
rest and the tint on hover. With an action and no title, a single-line description sits centred
on the action; a title or longer text keeps everything top-aligned.
API Reference
Alert
| Prop | Type | Default | Description |
|---|---|---|---|
live | boolean | — | |
variant | "default" | "destructive" | "info" | "success" | "warning" | null | — |
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).
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).
AlertAction
AlertAction adds no props of its own — it accepts everything the underlying element or Base UI primitive accepts (className, ref, ARIA attributes, event handlers).
Accessibility
- The root is a polite
role="status"region by default, so an alert present at page load is read in page order rather than interrupting (A11Y-3). Withlive, adestructiveorwarningalert is an assertiverole="alert"instead: use it only for a message the user's own action just caused, and render it when that happens. Aroleyou pass yourself still wins. - Status is never colour alone (A11Y-8): every variant takes an icon, and the title carries the words. The icon is decorative — the sentence is what gets read.
- Each variant takes its family's
-textink over the card surface (A11Y-13), which clears the AA contrast floor in both themes; the description sits at 90% opacity and still clears it. AlertActionholds a real control. Keep it aButtonso it is reachable by keyboard in the reading order, immediately after the description.
| Contract | States tested |
|---|---|
| Behaviour | default, error, open, saved, success, live |
| Accessibility | labeled, status-announcement, alert-announcement, semantic-html |
| Visual | default, hover, error, success |
Do / Don't
Deviations
Upstream's file plus packages/ui/upstream/patches/alert.patch. Every hunk:
- API-29 — each status variant gives every non-primary button inside it the family's own hover
(
bg-<family>/10 text-<family>-text), never the neutral hover that read white in dark mode;contrast-check.mjsgates the pair in both themes. - COL-12 —
success,warningandinfovariants, written in upstream's owndestructiveshape: one ink onbg-card, with a dimmed description. The four status families exist in the token contract; Alert is where they surface as a banner. - A11Y-13 — every status variant takes the family's
-textink rather than the fill. Upstream'stext-destructiveon card measures 3.98:1 in light, under the AA floor A11Y-1 enforces. - A11Y-8 — status is never colour alone: the page and
alert.test.tsxrequire an icon and a title beside the tint, and the class string reserves the icon column either way. - A11Y-3 —
Alerttakeslive?: boolean. The root is a politerole="status"for every variant, and takes upstream's assertiverole="alert"only withliveon adestructiveorwarningalert; a caller's ownrolestill wins. - LAY-15 —
AlertActionis a grid item in its own top-aligned column beside the title and description, and drops below the text when the alert is narrower than@md(28rem). Upstream positions itabsolute top-2 end-2and reserves onlype-18for it, so ansmlabel over seven characters reaches under the title (Action placement). Its children sit in a wrapping flex row with agap-2gap, so two actions need no wrapper (Two actions). - DOC-2 —
cnis imported from@vegastack/design.