Alert
A persistent, inline message that tells people something important about the page or task in front of them.
import { InfoIcon } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export default function AlertDemo() {
return (
<Alert variant="info" className="max-w-sm">
<InfoIcon />
<AlertTitle>Scheduled maintenance</AlertTitle>
<AlertDescription>
The dashboard will be read-only on Sunday from 02:00 to 03:00 UTC.
</AlertDescription>
</Alert>
)
}Anatomy
- 1IconTells the kind of message at a glance. It takes the variant's color but never carries the meaning alone.
- 2ContainerA bordered, tinted surface. The variant sets its colors and its role: status for most, alert for warnings and errors.
- 3TitleOne line that says what happened or what to know.
- 4DescriptionThe details and, when there is one, the next step. Neutral text.
Installation
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/alert.jsonUsage
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"<Alert variant="warning">
<TriangleAlertIcon />
<AlertTitle>Your trial ends in 3 days</AlertTitle>
<AlertDescription>Add a payment method to keep your projects running.</AlertDescription>
</Alert>Examples
Variants
Five variants: default is neutral, and the other four map to the status scales. A status variant tints its background with step 2, draws its border with step 6, colors its icon with step 11 and its title with step 12; default uses the card surface and the standard border. The description stays neutral in every variant, so the status reads at a glance and the detail reads comfortably, at 4.5:1 or more in both modes.
import {
CircleAlertIcon,
CircleCheckIcon,
InfoIcon,
TerminalIcon,
TriangleAlertIcon,
} from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export default function AlertVariants() {
return (
<div className="flex w-full max-w-lg flex-col gap-3">
<Alert>
<TerminalIcon />
<AlertTitle>New CLI release</AlertTitle>
<AlertDescription>
Version 4.2 adds registry namespaces and faster installs.
</AlertDescription>
</Alert>
<Alert variant="info">
<InfoIcon />
<AlertTitle>Invitations expire after 7 days</AlertTitle>
<AlertDescription>
Resend an invitation at any time from the members list.
</AlertDescription>
</Alert>
<Alert variant="success">
<CircleCheckIcon />
<AlertTitle>Domain verified</AlertTitle>
<AlertDescription>
acme.com is ready. Certificates renew automatically.
</AlertDescription>
</Alert>
<Alert variant="warning">
<TriangleAlertIcon />
<AlertTitle>You've used 90% of your build minutes</AlertTitle>
<AlertDescription>
Builds will queue once you reach the limit on May 31.
</AlertDescription>
</Alert>
<Alert variant="destructive">
<CircleAlertIcon />
<AlertTitle>Payment failed</AlertTitle>
<AlertDescription>
We couldn't charge the card ending in 4242. Update it to keep
your workspace active.
</AlertDescription>
</Alert>
</div>
)
}With an action
Place one follow-up action in AlertAction. It sits on the right, vertically centered, in a column of its own: the text wraps beside it, however wide the action is. Keep it to a single small button; an alert with a toolbar is a card.
import { SparklesIcon } from "lucide-react"
import {
Alert,
AlertAction,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
import { Button } from "@/components/ui/button"
export default function AlertWithAction() {
return (
<Alert variant="info" className="max-w-lg">
<SparklesIcon />
<AlertTitle>Preview environments are here</AlertTitle>
<AlertDescription>
Every pull request now gets its own URL.
</AlertDescription>
<AlertAction>
<Button size="xs" variant="outline">
Enable
</Button>
</AlertAction>
</Alert>
)
}With a link
Links inside AlertDescription are underlined, set in medium weight and inherit the description's neutral text color, so they stay legible on every tint.
import { TriangleAlertIcon } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export default function AlertWithLink() {
return (
<Alert variant="warning" className="max-w-lg">
<TriangleAlertIcon />
<AlertTitle>Node.js 20 reaches end of life in April</AlertTitle>
<AlertDescription>
Three projects still build on Node.js 20.{" "}
<a href="#">Review affected projects</a> before builds start failing.
</AlertDescription>
</Alert>
)
}With a list
When several things need fixing, list them. People scan lists; they skim paragraphs.
Fix these issues, then try again:
- The page title is empty.
- Two images are missing alternative text.
- The canonical URL points to a deleted page.
import { CircleAlertIcon } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export default function AlertWithList() {
return (
<Alert variant="destructive" className="max-w-lg">
<CircleAlertIcon />
<AlertTitle>We couldn't publish your changes</AlertTitle>
<AlertDescription>
<p>Fix these issues, then try again:</p>
<ul className="list-disc pl-5 [&>li]:mt-1">
<li>The page title is empty.</li>
<li>Two images are missing alternative text.</li>
<li>The canonical URL points to a deleted page.</li>
</ul>
</AlertDescription>
</Alert>
)
}Title only
A short message doesn't need a description. The icon is optional — drop it for neutral notes that shouldn't draw the eye.
import { CircleCheckIcon } from "lucide-react"
import { Alert, AlertTitle } from "@/components/ui/alert"
export default function AlertMinimal() {
return (
<div className="flex w-full max-w-md flex-col gap-3">
<Alert variant="success">
<CircleCheckIcon />
<AlertTitle>Your changes were saved.</AlertTitle>
</Alert>
<Alert>
<AlertTitle>
Drafts are only visible to you and your editors.
</AlertTitle>
</Alert>
</div>
)
}Guidelines
When to use
- To explain a condition that affects the whole page or section: an outage, a limit, a pending verification.
- To summarize a set of form errors above the form, in addition to inline errors on each field.
- To surface information that must stay visible until the situation changes.
When not to use
- For confirmation of something the person just did — use a Toast. It appears where attention already is and disappears on its own.
- For errors on a single field — use
FieldErrorinside a Field, next to the input. - For decisions that block progress — use an Alert Dialog.
- For marketing content. An alert borrows the urgency of status colors; spending it on promotions teaches people to ignore it.
Choose the lowest variant that is true
Status colors are a finite budget. If nothing is wrong, the alert is default or info, even when the message feels important. Reserve warning for things that will break, and destructive for things that are broken.
Writing
- Lead with the consequence, not the cause: Builds will queue once you reach the limit, not Build minute usage is at 90%.
- Say what to do next. Every warning and error should name an action or link to one.
- Keep titles to one line and descriptions to two sentences. Longer content belongs on its own page.
- Don't stack alerts. Two or more alerts in one place compete; combine them or show the most severe.
Accessibility
Alerts are live regions, so their content is announced when it appears without moving focus.
- Politeness follows severity.
destructiveandwarningrenderrole="alert"and are announced immediately, interrupting whatever the screen reader was saying. All other variants renderrole="status"and wait for a pause. Passroleto override, for examplerole="note"for static content that should not be announced at all. - Insert, don't reveal. Live regions announce changes. An alert that is present on page load is read in document order; one added later — after a failed submission, say — is announced as it appears.
- Color is never the only signal. Pair every status variant with an icon and a title that states the status in words.
- Actions stay in the tab order. Buttons and links inside an alert are reachable with Tab and never steal focus when the alert appears.
API reference
Alert
The container. Renders a <div> with data-slot="alert" and a data-variant attribute.
AlertTitle
A single line that states the message. Renders a <div>; when the alert has an icon, it starts in the second column.
AlertDescription
Supporting text, links and lists. Uses the neutral muted-foreground color in every variant, so only the icon and the title carry the status color.
AlertAction
A slot for one follow-up action. It takes a column of its own at the right edge, vertically centered, so the text wraps beside it.