Components

Alert

Static banner that surfaces a piece of context above content. Five tones (default / info / warning / success / muted). Never for transient feedback — use Toast for that.

Updated Jul 21, 2026 by Juan Pablo Turina

Anatomy

  1. 1
    Alert (root)

    The div with role='alert'. rounded-lg border bg-card px-4 py-3. Adds pr-9 automatically when onDismiss is set so the X never overlaps content.

  2. 2
    Icon slot

    First child. A Phosphor icon at weight='light' className='size-4'. Positioned absolutely at left-4 top-3; the variant tints only this icon (destructive also tints title + description).

  3. 3
    AlertTitle

    h5 with text-sm font-medium and mb-1. Keep it one line. Everything after the icon is shifted right with pl-7 so it never collides.

  4. 4
    AlertDescription

    div with text-sm text-muted-foreground. Under destructive, it's automatically switched to text-destructive via a data-slot selector.

  5. 5
    AlertActions

    Optional flex-wrap row of Button variant='outline' size='sm' below the description. Text is reset to foreground so buttons stay neutral inside a destructive alert.

  6. 6
    Dismiss (X)

    Rendered only when onDismiss is passed. Ghost X button pinned top-right (right-3 top-3), aria-label='Dismiss', wired to your close/hide state.

Variants

<Alert variant="info">
  <Info weight="light" className="size-4" />
  <AlertTitle>Heads up</AlertTitle>
  <AlertDescription>The rule you're editing is currently live.</AlertDescription>
</Alert>

With actions

<Alert>
  <Info weight="light" className="size-4" />
  <AlertTitle>Route updated</AlertTitle>
  <AlertDescription>Your changes are now live on all connected accounts.</AlertDescription>
  <AlertActions>
    <Button variant="outline" size="sm">Undo</Button>
  </AlertActions>
</Alert>

{/* Dismissable: pass onDismiss to render the X */}
<Alert variant="muted" onDismiss={() => {}}>
  <Info weight="light" className="size-4" />
  <AlertTitle>Test mode</AlertTitle>
  <AlertDescription>This account still shows Test mode traffic.</AlertDescription>
</Alert>

Inline action

Pass an action to render a right-aligned button (vertically centered) instead of the dismiss X. An alert is either dismissable or actionable, not both.

{/* Button on the right, vertically centered — no dismiss X */}
<Alert action={<Button variant="outline" size="sm">Undo</Button>}>
  <CheckCircle weight="light" className="size-4" />
  <AlertTitle>Rule archived</AlertTitle>
  <AlertDescription>You can restore it from the archive at any time.</AlertDescription>
</Alert>
Which action pattern to use
The need shapes the alert, but the button placement is a rule, not a free choice. If the alert has a call to action, the default is a single right-aligned button with no dismiss X (action). Move buttons below the description only when you also need a longer message AND the alert must stay dismissable (AlertActions + onDismiss). No button? A plain alert, optionally dismissable via onDismiss.

Recipes

Ready-to-copy compositions covering the most common Yuno usages of this atom.

Info banner with dismiss

The default persistent notice above a page or form. Info tone + X so users can hide it once acknowledged. Use for 'test mode is on', 'you're viewing a shared view', 'this account is read-only'.

<Alert variant="info" onDismiss={() => setOpen(false)}>
  <Info weight="light" className="size-4" />
  <AlertTitle>Test mode is on</AlertTitle>
  <AlertDescription>
    You're viewing sandbox data. Switch to Live in the top bar to see real traffic.
  </AlertDescription>
</Alert>
Destructive alert with recovery actions

Red icon + red title + red description communicate a real problem. Pair with outline buttons in AlertActions so the user has an immediate next step (Retry, Contact support). Reserved for actual failures, not routine 'delete' flows.

<Alert variant="destructive">
  <WarningCircle weight="light" className="size-4" />
  <AlertTitle>Payment gateway is failing</AlertTitle>
  <AlertDescription>
    3 transactions were rejected in the last hour by Stripe. Retry or contact support.
  </AlertDescription>
  <AlertActions>
    <Button variant="outline" size="sm">Retry all</Button>
    <Button variant="outline" size="sm">Contact support</Button>
  </AlertActions>
</Alert>
Success confirmation (persistent)

Green check for a state that should remain visible after an action completes ('rule published', 'export ready'). If the message is transient - a toast fits better.

<Alert variant="success" onDismiss={() => setOpen(false)}>
  <CheckCircle weight="light" className="size-4" />
  <AlertTitle>Rule published</AlertTitle>
  <AlertDescription>
    The rule is now active on all connected accounts.
  </AlertDescription>
</Alert>
Upsell / feature announcement

Neutral default tone + dismiss + two outline actions (Learn more, Enable). Use to surface a new capability inline above the affected surface - never inside a Dialog.

<Alert onDismiss={() => setOpen(false)}>
  <Info weight="light" className="size-4" />
  <AlertTitle>Smart routing is now available</AlertTitle>
  <AlertDescription>
    Route each transaction to the best provider automatically based on cost and success rate.
  </AlertDescription>
  <AlertActions>
    <Button variant="outline" size="sm">Learn more</Button>
    <Button variant="outline" size="sm">Enable</Button>
  </AlertActions>
</Alert>

Import

Copy this import line at the top of the file where you compose this atom.

AlertActions is optional — only import it when composing buttons below the description.
import {
  Alert,
  AlertTitle,
  AlertDescription,
  AlertActions,
} from "@/components/ui/alert";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
Alert.variant"default" | "info" | "warning" | "success" | "muted" | "destructive""default"Tone. Only tints the icon (destructive also reddens the title + description). All variants render on the same white card + neutral border surface.
Alert.onDismiss() => voidWhen provided, renders an X button in the top-right corner and reserves pr-9 spacing so content never overlaps it. Wire it to your close/hide state. Ignored when `action` is set.
Alert.actionReactNodeA right-aligned action (e.g. a Button variant='outline' size='sm'), vertically centered next to the content. Replaces the dismiss X — an alert is either dismissable or actionable, not both.
Alert.classNamestringMerged. The default surface is rounded-lg border bg-card px-4 py-3 — override sparingly.
Alert.childrenReactNodeCompose in this order: <Icon weight='light' className='size-4' />, <AlertTitle>, <AlertDescription>, then optional <AlertActions>. The icon is positioned absolutely; children after it get pl-7 automatically.
AlertTitle.classNamestringMerged. Default is mb-1 text-sm font-medium. Keep the title one line.
AlertDescription.classNamestringMerged. Default is text-sm text-muted-foreground. Under destructive, an override to text-destructive is applied automatically.
AlertActions.classNamestringMerged. Default is mt-3 flex flex-wrap gap-2 text-foreground. Compose Button variant='outline' size='sm' inside. text-foreground is intentional so buttons stay neutral inside a destructive Alert.

When to use

  • Explaining a persistent state above a form or table.
  • Highlighting a limitation or a change the user should be aware of before acting.

When not to use

  • Transient confirmations — use Toast.
  • Blocking modals — use Dialog.

Usage

Do
  • Include an icon that matches the tone (Info / Warning / CheckCircle).
  • Keep the title one line and the description under two sentences.
  • When the alert needs a button, default to a single right-aligned action (no X). Move buttons below the description only for longer text that must also stay dismissable.
Don't
  • Don't stack more than one Alert per surface.
  • Don't use tone='warning' (destructive) as decoration.
  • Don't pair the dismiss X with a right-aligned action — an alert is dismissable or actionable, not both.

Related

Cross-links to atoms and patterns you may reach for next.

  • CalloutDocs-only equivalent used inside kit pages (tinted background, richer body). Alert is the product-facing atom.
  • ToastFor transient feedback after an action ('Rule created successfully.'). Alert stays; Toast disappears.
  • DialogFor blocking decisions the user must resolve. Alert informs in-place; Dialog interrupts.
  • Alert dialogFor destructive confirmations. The red text-only Alert never asks 'are you sure' - Alert dialog does.
  • BadgeFor inline status inside a row or header instead of a full-width banner.