Skip to content
Corsair UI
Browse the docs

ComponentsNo. 03 of 109

Alert

Callout for important messages on a neutral surface; default, success, warning and destructive tones colour the icon.

Installation

pnpm dlx shadcn@latest add @corsair-ui/alert

No setup needed: the CLI finds @corsair-ui in the shadcn registry directory. The files land in your project as source: edit them like your own code. More in Installation.

Also adds
utils
npm
class-variance-authorityclsxtailwind-merge

Examples

Tones

Only the icon takes the tone. Non-urgent messages use role="status".

Heads up
Components are copied into your project, so you can edit them.
Payment received
Your booking is confirmed.
Card expires soon
Update it before the next charge on the 5th.

Title only

Changes saved.

Accessibility

  • role="alert" interrupts screen readers; pass role="status" for messages that are not urgent.
  • The tone is on the icon only, so the title has to say what happened.

Compatibility

Tailwind CSS
3.4 and 4, both checked in CI
React
19
Rendering
Works in server components

Source

1 file, installed as source you own
alert.tsxView on GitHub
import { cva, type VariantProps } from "class-variance-authority";
import type { ComponentProps } from "react";

import { cn } from "@/registry/default/lib/utils";

const alertVariants = cva(
  [
    "bg-card text-card-foreground relative grid w-full grid-cols-[0_1fr] items-start gap-y-1 rounded-lg border px-4 py-3 text-sm",
    "has-[>svg]:grid-cols-[1rem_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5",
  ],
  {
    variants: {
      // Every tone shares the neutral surface; only the icon takes the colour.
      variant: {
        default: "[&>svg]:text-foreground",
        destructive: "[&>svg]:text-destructive",
        success: "[&>svg]:text-success",
        warning: "[&>svg]:text-warning",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
);

/**
 * A message that draws attention. The tone shows on the icon, so put one
 * first; the title should still say what happened on its own.
 *
 * It uses `role="alert"`, which interrupts screen readers: pass
 * `role="status"` for messages that are not urgent.
 */
function Alert({
  className,
  variant,
  ...props
}: ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
  return (
    <div
      role="alert"
      data-slot="alert"
      data-variant={variant ?? "default"}
      className={cn(alertVariants({ variant }), className)}
      {...props}
    />
  );
}

function AlertTitle({ className, ...props }: ComponentProps<"div">) {
  return (
    <div
      data-slot="alert-title"
      className={cn("col-start-2 min-h-4 leading-5 font-medium tracking-tight", className)}
      {...props}
    />
  );
}

function AlertDescription({ className, ...props }: ComponentProps<"div">) {
  return (
    <div
      data-slot="alert-description"
      className={cn(
        "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
        className
      )}
      {...props}
    />
  );
}

export { Alert, AlertDescription, AlertTitle, alertVariants };