# Shadcn Alert

> Free shadcn/ui alert component for React — an inline message banner with an icon, title, and description. Default and destructive variants plus success/warning/info, actions, dismissible, and a full-width banner.

Source: https://designrevision.com/components/alert

The **Shadcn Alert** is an **inline message banner** — a bordered box with an optional icon, a title, and a description that surfaces a status or notice in the page flow. It ships **default** and **destructive** variants, lays out its icon automatically, and restyles easily for success, warning, and info. The examples below cover variants, icons, actions, a dismissible alert, and a full-width banner.

## Alert vs Alert Dialog

These are two different components — don't mix them up:

- **Alert** (this page) — an **inline** message that lives in the layout. A banner, a form-error summary, a notice.
- **[Alert Dialog](/components/alert-dialog)** — a **modal** that interrupts the user to confirm or cancel a destructive action.

If you want a message *in* the page, use Alert. If you need a blocking confirm, use Alert Dialog.

## Anatomy

Three parts, composed:

```tsx
<Alert>
  <TerminalIcon />
  <AlertTitle>Heads up!</AlertTitle>
  <AlertDescription>
    You can add components to your app using the CLI.
  </AlertDescription>
</Alert>
```

Drop a Lucide icon as the **first child** and the component's CSS grid detects it (`has-[>svg]`) and creates an icon column automatically. With no icon, that column collapses and the content spans the full width.

## Variants

Two are built in:

```tsx
<Alert variant="destructive">
  <CircleAlertIcon />
  <AlertTitle>Error</AlertTitle>
  <AlertDescription>Your session has expired.</AlertDescription>
</Alert>
```

For **success / warning / info**, override the border, text, and icon color with a `className` (the Success / warning / info example shows green, amber, and blue). If you use them often, add them to the `cva` variants so `variant="success"` works directly.

## Actions and dismissing

- **Actions** — add buttons under the content (aligned to the text column with `col-start-2`) for "Update now / Later" style notices.
- **Dismissible** — track an open state and render a corner close button (the Dismissible example uses `useState`). For transient, stacking notifications instead, reach for a **[toast](/components/sonner)** (Sonner).

## Announcement banner

For a high-emphasis, full-width bar, give the Alert a colored background and an inline link — the Announcement banner example uses `bg-primary text-primary-foreground` for a promo or notice at the top of a page.

## Accessibility

The Alert sets `role="alert"`, so assistive tech announces its content as it appears — right for important, time-sensitive messages. For routine notices you can soften the urgency (e.g. `role="status"`). Keep the meaning in the title and description; decorative icons are not announced.

## Installation

### alert

**Install:**

```bash
npx shadcn@latest add @designrevision/alert
```

**Dependencies:** utils

**Props**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| variant | "default" \| "destructive" | "default" | Visual style. default for neutral messages, destructive for errors. |

**Usage & accessibility:** An inline alert (a message banner) — distinct from Alert Dialog (the modal). Compose <Alert> with <AlertTitle> and <AlertDescription>; drop a Lucide icon as the first child and the CSS grid lays it out automatically. variant is "default" or "destructive" (extend the cva for success/warning/info). It carries role="alert" so screen readers announce it.

```tsx
// components/ui/alert.tsx
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const alertVariants = cva(
  "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
  {
    variants: {
      variant: {
        default: "bg-card text-card-foreground",
        destructive:
          "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
      },
    },
    defaultVariants: {
      variant: "default",
    },
  }
)

function Alert({
  className,
  variant,
  ...props
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
  return (
    <div
      data-slot="alert"
      role="alert"
      className={cn(alertVariants({ variant }), className)}
      {...props}
    />
  )
}

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

function AlertDescription({
  className,
  ...props
}: React.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, AlertTitle, AlertDescription }
```

## Examples

### Default & destructive

The canonical alert — icon, title, and description in the two built-in variants.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-demo-01
```

**Dependencies:** lucide-react, alert

```tsx
// components/ui/alert-demo-01.tsx
import { CircleAlertIcon, TerminalIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

export default function AlertDemo01() {
  return (
    <div className="w-full max-w-md space-y-4">
      <Alert>
        <TerminalIcon />
        <AlertTitle>Heads up!</AlertTitle>
        <AlertDescription>
          You can add components to your app using the CLI.
        </AlertDescription>
      </Alert>
      <Alert variant="destructive">
        <CircleAlertIcon />
        <AlertTitle>Error</AlertTitle>
        <AlertDescription>
          Your session has expired. Please log in again.
        </AlertDescription>
      </Alert>
    </div>
  )
}
```

---

### Success / warning / info

Extra status colors built by overriding the border, text, and icon color.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-variants-01
```

**Dependencies:** lucide-react, alert

```tsx
// components/ui/alert-variants-01.tsx
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

export default function AlertVariants01() {
  return (
    <div className="w-full max-w-md space-y-4">
      <Alert className="border-green-500/50 text-green-700 dark:text-green-400 [&>svg]:text-green-600">
        <CircleCheckIcon />
        <AlertTitle>Success</AlertTitle>
        <AlertDescription className="text-green-700/80 dark:text-green-400/80">
          Your changes have been saved.
        </AlertDescription>
      </Alert>
      <Alert className="border-amber-500/50 text-amber-700 dark:text-amber-400 [&>svg]:text-amber-600">
        <TriangleAlertIcon />
        <AlertTitle>Warning</AlertTitle>
        <AlertDescription className="text-amber-700/80 dark:text-amber-400/80">
          Your trial ends in 3 days.
        </AlertDescription>
      </Alert>
      <Alert className="border-blue-500/50 text-blue-700 dark:text-blue-400 [&>svg]:text-blue-600">
        <InfoIcon />
        <AlertTitle>Information</AlertTitle>
        <AlertDescription className="text-blue-700/80 dark:text-blue-400/80">
          A new version is available.
        </AlertDescription>
      </Alert>
    </div>
  )
}
```

---

### Title-only & description-only

Minimal alerts — the icon column collapses automatically when there's no icon.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-simple-01
```

**Dependencies:** lucide-react, alert

```tsx
// components/ui/alert-simple-01.tsx
import { CheckIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

export default function AlertSimple01() {
  return (
    <div className="w-full max-w-md space-y-4">
      {/* Title only, with an icon */}
      <Alert>
        <CheckIcon />
        <AlertTitle>Your changes have been saved.</AlertTitle>
      </Alert>
      {/* Description only, no icon — the grid collapses the icon column */}
      <Alert>
        <AlertDescription>
          We use cookies to improve your experience.
        </AlertDescription>
      </Alert>
    </div>
  )
}
```

---

### With actions

Trailing action buttons aligned under the content — the update/notice pattern.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-action-01
```

**Dependencies:** lucide-react, alert, button

```tsx
// components/ui/alert-action-01.tsx
import { RocketIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Button } from "@/components/ui/button"

export default function AlertAction01() {
  return (
    <Alert className="w-full max-w-md">
      <RocketIcon />
      <AlertTitle>Update available</AlertTitle>
      <AlertDescription>
        A new version is ready to install.
      </AlertDescription>
      <div className="col-start-2 mt-2 flex gap-2">
        <Button size="sm">Update now</Button>
        <Button size="sm" variant="ghost">
          Later
        </Button>
      </div>
    </Alert>
  )
}
```

---

### Dismissible

A closable alert — an X button toggles it with `useState`.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-dismissible-01
```

**Dependencies:** lucide-react, alert, button

```tsx
// components/ui/alert-dismissible-01.tsx
"use client"

import * as React from "react"
import { InfoIcon, XIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Button } from "@/components/ui/button"

export default function AlertDismissible01() {
  const [open, setOpen] = React.useState(true)

  if (!open) {
    return (
      <Button variant="outline" size="sm" onClick={() => setOpen(true)}>
        Show alert
      </Button>
    )
  }

  return (
    <Alert className="relative w-full max-w-md pr-12">
      <InfoIcon />
      <AlertTitle>New feature</AlertTitle>
      <AlertDescription>
        Dark mode is now available in settings.
      </AlertDescription>
      <Button
        variant="ghost"
        size="icon"
        className="absolute top-2 right-2 size-7"
        onClick={() => setOpen(false)}
      >
        <XIcon />
        <span className="sr-only">Dismiss</span>
      </Button>
    </Alert>
  )
}
```

---

### Announcement banner

A full-width, high-emphasis banner — a colored Alert with an inline link.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-banner-01
```

**Dependencies:** lucide-react, alert

```tsx
// components/ui/alert-banner-01.tsx
import { MegaphoneIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

export default function AlertBanner01() {
  return (
    <Alert className="bg-primary text-primary-foreground border-primary w-full [&>svg]:text-current">
      <MegaphoneIcon />
      <AlertTitle>Black Friday — 50% off all plans</AlertTitle>
      <AlertDescription className="text-primary-foreground/90">
        Offer ends Monday.{" "}
        <a href="#" className="font-medium underline underline-offset-2">
          Claim it now
        </a>
        .
      </AlertDescription>
    </Alert>
  )
}
```

---

### With a list

A destructive alert whose description holds a bulleted list — a form-error summary.

**Install:**

```bash
npx shadcn@latest add @designrevision/alert-list-01
```

**Dependencies:** lucide-react, alert

```tsx
// components/ui/alert-list-01.tsx
import { CircleAlertIcon } from "lucide-react"

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"

export default function AlertList01() {
  return (
    <Alert variant="destructive" className="w-full max-w-md">
      <CircleAlertIcon />
      <AlertTitle>Unable to submit your form</AlertTitle>
      <AlertDescription>
        <ul className="list-inside list-disc text-sm">
          <li>Email is required</li>
          <li>Password must be at least 8 characters</li>
          <li>You must accept the terms</li>
        </ul>
      </AlertDescription>
    </Alert>
  )
}
```
