rapidUI

Alert

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.json

Installs to @/components/ui/alert.

Manual installation

Install the dependencies:

pnpm add class-variance-authority@^0.7.1

Copy the source into your project:

components/ui/alert.tsx
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, success and warning
  • Optional leading icon: place an svg as the first child and the layout switches to a two-column grid
  • Composable AlertTitle, AlertDescription and AlertAction
  • AlertAction pins a button to the top-right corner
  • Links inside title and description are underlined automatically
  • A role that follows the variant: alert for destructive, status for the others. Override it with the role prop
  • data-slot attributes 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:

RoleDefault forAnnouncementUse it for
alertdestructiveAt once, interrupting what is being readErrors and urgent messages that appear after an action: a failed submission, a session about to end
statusdefault, info, success, warningWhen the screen reader is idle, and only if the alert appears after the page has loadedConfirmations and updates: a saved draft, a sent application
note or none–Never; it is read in its place on the pageStatic 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; accepts variant ('default' | 'destructive' | 'info' | 'success' | 'warning', default 'default'), role (default 'alert' for destructive, 'status' otherwise) and all div attributes
  • AlertTitle - The alert title (renders an h5)
  • AlertDescription - The alert description/content
  • AlertAction - Absolutely positioned slot for an action button in the top-right corner

Variants

  • default - Neutral alert for general information
  • destructive - Alert for errors and critical information
  • info - Primary tint for information the user should notice
  • success - Green tint for confirmations, such as a sent application or a granted permit
  • warning - 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

  • destructive alerts use role="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, and role="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 AlertAction an aria-label

Best Practices

  1. Choose appropriate variants:

    • Use default for general notices
    • Use info, success and warning for status messages
    • Use destructive for errors and critical information
  2. Content guidelines:

    • Keep titles concise and descriptive
    • Provide clear, actionable descriptions
    • Use icons that reinforce the message type
  3. 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>