Skip to content
Component installs need the registry setup
VegaStack Design

Alert

Displays a callout for user attention — five semantic variants, an optional icon, a title, a description, and an action.

Status
stable
Since
0.1.0
Accessibility pattern
role status, alert only when live, icon beside the label

Last updated

Payment successful
Your payment of $29.99 has been processed. A receipt has been sent to your email address.
New feature available
We've added dark mode support. You can enable it in your account settings.

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 alert

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/alert

Run 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>;
Payment successful
Your payment of $29.99 has been processed. A receipt has been sent to your email address.
New feature available
We've added dark mode support. You can enable it in your account settings.

Anatomy

Alert — data-slot="alert"
AlertAction — data-slot="alert-action"
AlertDescription — data-slot="alert-description"
AlertTitle — data-slot="alert-title"

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.

Heads up!
You can add components and dependencies to your app using the CLI.

Basic

A basic alert with an icon, a title and a description.

Account updated successfully
Your profile information has been saved. Changes will be reflected immediately.

Destructive

Use variant="destructive" for a failure the user has to act on.

Payment failed
Your payment could not be processed. Please check your payment method and try again.

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.

Deployment succeeded
Build 4127 is live on production.
Your subscription expires in 3 days
Renew now to avoid an interruption in service.
Maintenance window on Sunday
The API will be read-only between 02:00 and 04:00 UTC.

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.

Dark mode is now available
Enable it under your profile settings to get started.

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.

Your subscription will expire in 3 days.
Renew now to avoid service interruption, or upgrade to a paid plan to continue using the service.

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.

Payment successful
Your payment of $29.99 has been processed.
تم الدفع بنجاح
تمت معالجة دفعتك البالغة 29.99 دولارًا.

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.

Maintenance on Sunday
Present at load, so it is a polite status and is read in page order.

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.

Your trial ends in three days
Pick a plan to keep your workspace and its history.
Two files were removed (a narrow alert)
You can restore them for 30 days.

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.

Invitation pending
Sent to ada@example.com. The link expires in seven days.
Invitation pending (a narrow alert)
The link expires in seven days.

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.

Default alert with a title
The description sits under the title, top-aligned with the action.
You're viewing Sales as an admin.
A single line with no title and no action.
Info alert with a title
The description sits under the title, top-aligned with the action.
You're viewing Sales as an admin.
A single line with no title and no action.
Success alert with a title
The description sits under the title, top-aligned with the action.
You're viewing Sales as an admin.
A single line with no title and no action.
Warning alert with a title
The description sits under the title, top-aligned with the action.
You're viewing Sales as an admin.
A single line with no title and no action.
Destructive alert with a title
The description sits under the title, top-aligned with the action.
You're viewing Sales as an admin.
A single line with no title and no action.

API Reference

Alert

PropTypeDefaultDescription
liveboolean—
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). With live, a destructive or warning alert is an assertive role="alert" instead: use it only for a message the user's own action just caused, and render it when that happens. A role you 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 -text ink 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.
  • AlertAction holds a real control. Keep it a Button so it is reachable by keyboard in the reading order, immediately after the description.
ContractStates tested
Behaviourdefault, error, open, saved, success, live
Accessibilitylabeled, status-announcement, alert-announcement, semantic-html
Visualdefault, hover, error, success

Do / Don't

Do
Pair every status variant with an icon and a written title.
Don't
Signal severity with the tint alone, or mount an alert on page load just to show static copy.

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.mjs gates the pair in both themes.
  • COL-12 — success, warning and info variants, written in upstream's own destructive shape: one ink on bg-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 -text ink rather than the fill. Upstream's text-destructive on 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.tsx require an icon and a title beside the tint, and the class string reserves the icon column either way.
  • A11Y-3 — Alert takes live?: boolean. The root is a polite role="status" for every variant, and takes upstream's assertive role="alert" only with live on a destructive or warning alert; a caller's own role still wins.
  • LAY-15 — AlertAction is 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 it absolute top-2 end-2 and reserves only pe-18 for it, so an sm label over seven characters reaches under the title (Action placement). Its children sit in a wrapping flex row with a gap-2 gap, so two actions need no wrapper (Two actions).
  • DOC-2 — cn is imported from @vegastack/design.

On this page