Inline callout for status messages, with default and destructive variants and an optional action.
Installation
pnpm dlx shadcn@latest add https://rdf.dev.360online.com/r/alert.jsonInstalls to @/components/ui/alert.
Manual installation
Install the dependencies:
pnpm add class-variance-authority@^0.7.1Copy the source into your project:
import { cva, type VariantProps } from 'class-variance-authority'
import type * as React from 'react'
import { cn } from '@/lib/utils'
const alertVariants = cva(
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
default: 'bg-background text-foreground *:[svg]:text-foreground',
destructive:
'border-destructive-border bg-destructive-subtle text-foreground *:[svg]:text-destructive-subtle-foreground',
info: 'border-info-border bg-info-subtle text-foreground *:[svg]:text-info-subtle-foreground',
success: 'border-success-border bg-success-subtle text-foreground *:[svg]:text-success-subtle-foreground',
warning: 'border-warning-border bg-warning-subtle text-foreground *:[svg]:text-warning-subtle-foreground',
},
},
defaultVariants: {
variant: 'default',
},
},
)
/**
* A callout for an inline message.
*
* The default `role` follows the variant: `destructive` is `alert`, which screen readers announce at once and
* interrupt the user for; every other variant is `status`, which is announced politely when the message appears after
* the page has loaded and stays quiet when it is there from the start. Pass `role="alert"` for an urgent message in
* another variant, or `role="note"` (or `role={undefined}`) for static text that should never be announced.
*/
function Alert({ className, variant, ...props }: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
return (
<div
data-slot="alert"
role={variant === 'destructive' ? 'alert' : 'status'}
className={cn(alertVariants({ variant }), className)}
{...props}
/>
)
}
function AlertTitle({ className, ...props }: React.ComponentProps<'h5'>) {
return (
<h5
data-slot="alert-title"
className={cn(
'font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground',
className,
)}
{...props}
/>
)
}
function AlertDescription({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="alert-description"
className={cn(
'text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4',
className,
)}
{...props}
/>
)
}
function AlertAction({ className, ...props }: React.ComponentProps<'div'>) {
return <div data-slot="alert-action" className={cn('absolute top-2 right-2', className)} {...props} />
}
export { Alert, AlertTitle, AlertDescription, AlertAction }A versatile alert component for displaying callouts and inline messages. Built with class-variance-authority and styled with Tailwind CSS for consistent visual hierarchy.
Features
- Five variants:
default,destructive,info,successandwarning - Optional leading icon: place an
svgas the first child and the layout switches to a two-column grid - Composable
AlertTitle,AlertDescriptionandAlertAction AlertActionpins a button to the top-right corner- Links inside title and description are underlined automatically
- A
rolethat follows the variant:alertfordestructive,statusfor the others. Override it with theroleprop data-slotattributes on every part
Usage
import { Alert, AlertAction, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
import { CalendarClockIcon, WrenchIcon } from 'lucide-react'
export function ServiceNotices() {
return (
<div className="flex flex-col gap-4">
{/* Simple alert */}
<Alert>
<WrenchIcon />
<AlertTitle>Planned maintenance on Saturday</AlertTitle>
<AlertDescription>
E-services will be unavailable on 14 March 2026 between 22:00 and 02:00.
</AlertDescription>
</Alert>
{/* With action */}
<Alert>
<CalendarClockIcon />
<AlertTitle>Your parking permit expires in 12 days</AlertTitle>
<AlertDescription>Resident permit for zone C, valid until 10 April 2026.</AlertDescription>
<AlertAction>
<Button size="xs" variant="outline">
Renew
</Button>
</AlertAction>
</Alert>
</div>
)
}Examples
Default Alert
A neutral notice about planned maintenance of the e-services.
Variants
default for neutral notices, info for information worth noticing, success for confirmations, warning for things
the user should act on soon, and destructive for errors that stop them.
Status Messages
Service messages with the success, info and warning variants. The tinted background and icon colour give each
message its tone, but the icon and title carry the meaning, so status never relies on colour alone.
<Alert variant="warning">
<TriangleAlertIcon />
<AlertTitle>Water outage on Kungsgatan</AlertTitle>
<AlertDescription>Kungsgatan 1–27 is without water until about 15:00.</AlertDescription>
</Alert>Roles
The role decides how a screen reader announces the message:
| Role | Default for | Announcement | Use it for |
|---|---|---|---|
alert | destructive | At once, interrupting what is being read | Errors and urgent messages that appear after an action: a failed submission, a session about to end |
status | default, info, success, warning | When the screen reader is idle, and only if the alert appears after the page has loaded | Confirmations and updates: a saved draft, a sent application |
note or none | – | Never; it is read in its place on the page | Static guidance that is there from the start: processing times, opening hours |
// Static guidance, never announced
<Alert role="note">…</Alert>
// An urgent warning, announced at once
<Alert variant="warning" role="alert">…</Alert>
// No role at all
<Alert role={undefined}>…</Alert>With Action
AlertAction places a button, such as an action or a dismiss button, in the top-right corner.
With List
Summarise form errors at the top of a form and link each one to its field.
Compact
Title-only or description-only alerts for short, single-line messages.
Subcomponents
Alert- The container; acceptsvariant('default' | 'destructive' | 'info' | 'success' | 'warning', default'default'),role(default'alert'fordestructive,'status'otherwise) and alldivattributesAlertTitle- The alert title (renders anh5)AlertDescription- The alert description/contentAlertAction- Absolutely positioned slot for an action button in the top-right corner
Variants
default- Neutral alert for general informationdestructive- Alert for errors and critical informationinfo- Primary tint for information the user should noticesuccess- Green tint for confirmations, such as a sent application or a granted permitwarning- Amber tint for things that need attention, such as missing documents or a service disruption
The status variants keep body text in foreground and colour only the border, background and icon, so text contrast
stays above 4.5:1 in light and dark mode.
Accessibility
destructivealerts userole="alert", which screen readers announce immediately and interrupt the user for. Keep it for errors and time-sensitive messages- The other variants use
role="status": announced politely when the alert appears after the page has loaded, and silent when it is on the page from the start. This covers WCAG 2.2 success criterion 4.1.3 (Status Messages) without interrupting - Pass
role="alert"for an urgent message in another variant, androle="note"for static guidance that should never be announced - Live regions are announced most reliably when the alert is added to a page that is already loaded. For a message shown after navigation, move focus to it or to the page heading instead
- Icons are decorative; make sure the title or description conveys the meaning. Status is carried by text and an icon, never by colour alone
- Give icon-only buttons in
AlertActionanaria-label
Best Practices
-
Choose appropriate variants:
- Use
defaultfor general notices - Use
info,successandwarningfor status messages - Use
destructivefor errors and critical information
- Use
-
Content guidelines:
- Keep titles concise and descriptive
- Provide clear, actionable descriptions
- Use icons that reinforce the message type
-
Layout considerations:
- Place alerts near the content they relate to
- Use consistent spacing between multiple alerts
Common Patterns
Form Validation
<Alert variant="destructive">
<CircleAlertIcon />
<AlertTitle>Fix 2 problems before you send the application</AlertTitle>
<AlertDescription>
<ul className="list-inside list-disc">
<li><a href="#property">Property designation</a> is missing</li>
<li><a href="#site-plan">Site plan</a> must be a PDF file</li>
</ul>
</AlertDescription>
</Alert>Success Notification
<Alert variant="success">
<CheckCircle2Icon />
<AlertTitle>Application sent</AlertTitle>
<AlertDescription>
Your case number is 2026-04812. We have sent a confirmation to your email.
</AlertDescription>
</Alert>Dismissible Banner
<Alert>
<InfoIcon />
<AlertDescription>
From 1 June the city library is open until 20:00 on weekdays.
</AlertDescription>
<AlertAction>
<Button size="icon-xs" variant="ghost" aria-label="Dismiss">
<XIcon />
</Button>
</AlertAction>
</Alert>