Skip to content
Monogem

Component · Navigation & Feedback

Alert

Overview

A static callout that draws attention to a piece of information in the flow of a page — a success confirmation, a warning about consequences, an error that needs fixing, a neutral note. Alert is persistent and non-dismissible: it stays until the surrounding content changes. A message that appears transiently, stacks, or auto-dismisses is Toast, not an Alert variant.

Anatomy

Container → optional leading intent icon → content (optional AlertTitle, optional AlertDescription). A visually hidden intent word (“Note:” / “Success:” / “Warning:” / “Error:”) precedes the content on every non-default intent, carrying the intent to assistive tech even though the icon is decorative — see Accessibility. No dismiss button, no action row: content that needs a “Retry” or “Undo” places that Button inside AlertDescription, and anything that needs a close affordance is a different component.

Live Example

Intents

Default alert
A short sentence explaining what happened and what, if anything, to do next.
Note:
Info alert
A short sentence explaining what happened and what, if anything, to do next.
Success:
Success alert
A short sentence explaining what happened and what, if anything, to do next.
Warning:
Warning alert
A short sentence explaining what happened and what, if anything, to do next.
Error:
Destructive alert
A short sentence explaining what happened and what, if anything, to do next.

Title only

Success:
Your changes have been saved.

No icon

Note:
Scheduled maintenance
The dashboard will be read-only on Sunday from 02:00–03:00 UTC.

Dynamically shown — caller adds the live-region role

Code Example

alert-showcase.tsx
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

const INTENTS = ["default", "info", "success", "warning", "destructive"] as const;

/**
* Live Alert example — Alert is a server component (no client JS). Shows the
* five intents with their per-intent icon and visually hidden intent word, a
* title-only alert, an icon-free alert, and the caller-owned `role` for a
* dynamically shown message (Alert sets no role itself).
*/
export function AlertShowcase() {
return (
<div className="flex flex-col gap-8">
<section className="flex flex-col gap-3">
<h3 className="text-sm font-medium leading-snug text-muted-foreground">
Intents
</h3>
<div className="flex flex-col gap-3">
{INTENTS.map((intent) => (
<Alert key={intent} intent={intent}>
<AlertTitle>
{intent[0].toUpperCase() + intent.slice(1)} alert
</AlertTitle>
<AlertDescription>
A short sentence explaining what happened and what, if anything,
to do next.
</AlertDescription>
</Alert>
))}
</div>
</section>

<section className="flex flex-col gap-3">
<h3 className="text-sm font-medium leading-snug text-muted-foreground">
Title only
</h3>
<Alert intent="success">
<AlertTitle>Your changes have been saved.</AlertTitle>
</Alert>
</section>

<section className="flex flex-col gap-3">
<h3 className="text-sm font-medium leading-snug text-muted-foreground">
No icon
</h3>
<Alert intent="info" icon={null}>
<AlertTitle>Scheduled maintenance</AlertTitle>
<AlertDescription>
The dashboard will be read-only on Sunday from 02:00–03:00 UTC.
</AlertDescription>
</Alert>
</section>

<section className="flex flex-col gap-3">
<h3 className="text-sm font-medium leading-snug text-muted-foreground">
Dynamically shown — caller adds the live-region role
</h3>
<Alert intent="destructive" role="alert">
<AlertTitle>Payment failed</AlertTitle>
<AlertDescription>
We couldn&rsquo;t charge your card. Update your payment method and
try again.
</AlertDescription>
</Alert>
</section>
</div>
);
}

Variants

One axis: intent. Five values.

IntentSurfaceBorderTitle + iconBodyIcon
default--card--border--card-foreground--card-foregroundnone
info--info-subtle--info-subtle-border--info-subtle-foreground--foregroundInfo
success--success-subtle--success-subtle-border--success-subtle-foreground--foregroundCircleCheck
warning--warning-subtle--warning-subtle-border--warning-subtle-foreground--foregroundTriangleAlert
destructive--destructive-subtle--destructive-subtle-border--destructive-subtle-foreground--foregroundOctagonAlert
  • default is the neutral callout — no colour, no icon, no new token. Use it when the message has no success/warning/error character.
  • The four feedback intents differ by icon shape and label, not colour alone — the icon is a distinct Lucide glyph per intent and the visually hidden intent word names it for screen readers.
  • Body copy stays --foreground (≥ 18:1 on every subtle surface). Only the title takes the intent colour — a coloured multi-line paragraph reads poorly and is harder to scan.
  • No size, elevation, or layout variant. An Alert is one width (its container’s), one padding.

Icon control

icon propResult
omittedThe per-intent default glyph (default gets none).
nullNo icon; the grid collapses to one column. The hidden intent word stays.
a nodeRendered as given. Mark it aria-hidden yourself if it is decorative.

States

StateLook
DefaultIntent colours as above. Alert has no interactive states of its own.

Alert is not interactive — nothing to hover, focus, activate, or disable. Any control inside an Alert (a link, a Button) carries its own states from its own component.

Usage Guidance

Tokens

Alert reads the feedback colour family — twelve semantic tokens (--{intent}-subtle, --{intent}-subtle-foreground, --{intent}-subtle-border for info / success / warning / destructive), defined for light and dark themes — plus existing tokens for the neutral default intent and all geometry. It defines no alert-* tokens of its own; Toast and form-field error surfaces share the same family. See Color — Feedback.

TokenWhere used
--info-subtle / --info-subtle-foreground / --info-subtle-borderinfo surface / title + icon / border
--success-subtle / --success-subtle-foreground / --success-subtle-bordersuccess surface / title + icon / border
--warning-subtle / --warning-subtle-foreground / --warning-subtle-borderwarning surface / title + icon / border
--destructive-subtle / --destructive-subtle-foreground / --destructive-subtle-borderdestructive surface / title + icon / border
--card / --card-foregrounddefault surface + text
--borderdefault border
--foregroundBody copy on every feedback intent
--radius-lgCorner radius — Radius’s “cards, popovers”
--scale-pxBorder width — Color’s default border recipe
--scale-4Container padding (16px)
--scale-5Icon size (20px) — Icons’s “default UI” size
--scale-3Icon-to-content gap (12px)
--scale-1Gap between title and description

Do / Don’t

Do

  • Match the intent to the message: success for a completed action, warning for a consequence to weigh, destructive for an error or failure, info for a neutral heads-up, default for a note with no feedback character.
  • Give the Alert a short, specific title — “Payment failed,” not “Error.”
  • Keep it to one idea. A second unrelated message is a second Alert.

Don’t

  • Use Alert for a transient confirmation that should fade on its own — that’s Toast.
  • Add a close button — Alert is persistent by contract.
  • Rely on the colour alone to carry the intent. The icon + title do that; keep them.

Accessibility

  • No implicit ARIA role. Visual intent (how it looks) and announcement urgency (whether a screen reader interrupts) are separate decisions. A persistent Alert that is on the page at load needs no live region — it is read in normal document order, and the visually hidden intent word (“Error:”, “Warning:”…) gives its meaning. Alert never sets role for you.
  • Dynamically shown Alert: the caller adds the role. role="status" (polite — waits for a pause) for confirmations and non-urgent info; role="alert" (assertive — interrupts) for an error the user must address now. Pass it as a prop; it lands on the container untouched.
  • The icon is aria-hidden — it is visual reinforcement. The intent survives without it via the hidden word and the title text.
  • Colour is never the only signal: distinct icon shape per intent, plus the intent word.
  • Contrast (WCAG 2.1 AA): body --foreground and title/icon --{intent}-subtle-foreground both clear AA on every --{intent}-subtle surface, in light and dark — the same feedback family Toast reuses unchanged.

Related Components / Patterns

  • Toast — transient feedback that appears without interrupting the user.
  • Form — reports whole-form success and failure.