Alert component
Alert surfaces contextual feedback inline with the content it relates to — a validation error under a form, a success message after a save, a warning banner at the top of a page. It renders with role="alert" so assistive technology announces it as soon as it appears, and unlike Toast it never leaves its place in the layout or auto-dismisses on its own.
Playground
Change a prop on the right and the preview updates. Switch to Code to copy what you see.
Recipes
Copy-paste patterns for the ways Alert actually gets used — each one a real, self-contained example.
Status colors
Colour maps to intent — success, warning, danger, info — and swaps the leading status icon to match.
<Alert color="success" title="Saved" description="Your changes are live." />
<Alert color="warning" title="Heads up" description="Your trial ends in 3 days." />
<Alert color="danger" title="Payment failed" description="Update your card to continue." />
<Alert color="info" title="Tip" description="You can theme this from one CSS file." />Variants
solid, soft, and bordered — soft is the everyday inline notice; solid draws maximum attention.
<Alert variant="solid" color="primary" title="Solid" />
<Alert variant="soft" color="primary" title="Soft" />
<Alert variant="bordered" color="primary" title="Bordered" />With actions
The actions slot holds buttons — a confirm/dismiss inline with the message.
<Alert
color="warning"
title="Unsaved changes"
description="Leave without saving?"
actions={
<>
<Button size="sm" variant="soft">Discard</Button>
<Button size="sm" color="primary">Save</Button>
</>
}
/>Dismissible
isClosable adds a × and, when uncontrolled, hides the alert on click — the standard dismissible banner.
<Alert
color="info"
title="New feature"
description="Recipes are now on every component page."
isClosable
/>Custom icon
Override the default status icon with your own, or hide it entirely with hideIcon.
<Alert color="primary" icon={<SparkleIcon />} title="Pro tip" description="Set your brand ramp once." />
<Alert color="default" hideIcon title="Plain notice" description="No icon, just text." />Feedback after an action
The most common place to reach for Alert is right after something happens — a form submits, a request fails, a background job finishes. Keep a small piece of state for whichever case applies, render the matching Alert conditionally, and pass isClosable with an onClose handler that clears that state so the user can dismiss it once they've read it.
const SaveFeedback = () => {
const [status, setStatus] = useState<"success" | "error" | null>(null);
async function handleSave() {
try {
await fetch("/api/profile", { method: "PATCH" });
setStatus("success");
} catch {
setStatus("error");
}
}
return (
<div className="flex flex-col gap-3">
{status === "success" && (
<Alert
color="success"
title="Saved"
description="Your profile changes were saved."
isClosable
onClose={() => setStatus(null)}
/>
)}
{status === "error" && (
<Alert
color="danger"
title="Couldn't save"
description="Something went wrong. Try again."
isClosable
onClose={() => setStatus(null)}
/>
)}
<Button onPress={handleSave} color="primary">Save changes</Button>
</div>
);
};Variant and color together
variant controls density, color controls meaning, and they're independent — pick both for the emphasis a message actually needs. solid (the default) fills the background with the color and reads as the most urgent; soft uses a translucent tint of the color, a good default for messages living inside a form or card where a solid block would compete with the rest of the page; bordered keeps just a colored edge and barely-there background, for messages that should be noticeable but not shout.
The seven color values (default, primary, secondary, info, success, warning, danger) each drive the built-in status icon automatically, so picking a success or danger color doesn't require also picking an icon — Alert already knows which one fits.
<Alert variant="solid" color="danger" title="Failed" description="The upload could not complete." />
<Alert variant="soft" color="warning" title="Heads up" description="You have unsaved changes." />
<Alert variant="bordered" color="info" title="Note" description="This setting applies to new members only." />Dismissible vs. persistent
isClosable adds a close button (and lets Escape dismiss it while it has focus) — reach for it on transient feedback like a save confirmation, where there's nothing left for the user to do but acknowledge it. Leave it off (the default) for a persistent alert the user needs to actually resolve, like a validation error still attached to an invalid field — closing it wouldn't fix the underlying problem, so removing the escape hatch keeps the message in front of them until the form is valid.
Alert supports both controlled and uncontrolled visibility. Pass isVisible yourself if you're already tracking the state elsewhere; otherwise just mount/unmount the Alert (as in the example above) and let onClose tell you when to unmount it.
Extra content: startContent, actions, endContent
Three optional slots sit around the title/description block for anything an inline text message alone can't cover. startContent renders above the icon/title/description row — useful for a small label or badge. actions renders directly below the description, for a button or two that respond to the alert ("Retry", "Undo", "View details"). endContent renders after actions, for something like a timestamp or a secondary link.
<Alert
color="danger"
title="Upload failed"
description="The file exceeded the 10 MB limit."
actions={
<Button size="sm" variant="soft" color="danger" onPress={retry}>
Try again
</Button>
}
isClosable
onClose={() => setShowError(false)}
/>Custom and hidden icons
Every color role has a sensible default icon baked in, so most usage never needs to touch it. When it does: pass icon with any ReactNode to replace it outright, hideIcon to remove the icon (and its wrapper) entirely, or hideIconWrapper to keep the icon but drop the circular background behind it — handy when the icon itself already reads clearly without extra framing.
Props
The full public API for Alert. Every prop is stable and intentionally typed.
Content
| Prop | Type | Default | Description |
|---|---|---|---|
| title | ReactNode | — | Alert title. |
| description | ReactNode | — | Alert body content. |
| icon | ReactNode | — | Overrides the default color-derived status icon. |
| startContent | ReactNode | — | Content rendered before the title/description block. |
| endContent | ReactNode | — | Content rendered after the title/description block. |
| actions | ReactNode | — | Action buttons rendered below the description. |
title
ReactNode
default: —
Alert title.
description
ReactNode
default: —
Alert body content.
icon
ReactNode
default: —
Overrides the default color-derived status icon.
startContent
ReactNode
default: —
Content rendered before the title/description block.
endContent
ReactNode
default: —
Content rendered after the title/description block.
actions
ReactNode
default: —
Action buttons rendered below the description.
Appearance
| Prop | Type | Default | Description |
|---|---|---|---|
| color | "default" | "primary" | "secondary" | "info" | "success" | "warning" | "danger" | default | Semantic color, also picks the default status icon. |
| variant | "solid" | "soft" | "bordered" | solid | Visual style variant. |
| shadow | "none" | "xs" | "xs-sm" | "sm" | "md" | "lg" | none | Box-shadow depth. |
| radius | "none" | "xs" | "xs-sm" | "sm" | "md" | "lg" | "full" | md | Border radius. |
| size | "xs" | "xs-sm" | "sm" | "md" | "lg" | "xl" | md | Alert size. |
color
"default" | "primary" | "secondary" | "info" | "success" | "warning" | "danger"
default: default
Semantic color, also picks the default status icon.
variant
"solid" | "soft" | "bordered"
default: solid
Visual style variant.
shadow
"none" | "xs" | "xs-sm" | "sm" | "md" | "lg"
default: none
Box-shadow depth.
radius
"none" | "xs" | "xs-sm" | "sm" | "md" | "lg" | "full"
default: md
Border radius.
size
"xs" | "xs-sm" | "sm" | "md" | "lg" | "xl"
default: md
Alert size.
Behavior & states
| Prop | Type | Default | Description |
|---|---|---|---|
| isVisible | boolean | — | Controlled visibility; uncontrolled defaults visible. |
| isClosable | boolean | false | Shows a close button. |
| hideIcon | boolean | false | Hides the status icon entirely. |
| hideIconWrapper | boolean | false | Hides the icon's background wrapper, keeping the icon itself. |
| closeButtonProps | Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type"> | — | Extra props forwarded to the close button. |
isVisible
boolean
default: —
Controlled visibility; uncontrolled defaults visible.
isClosable
boolean
default: false
Shows a close button.
hideIcon
boolean
default: false
Hides the status icon entirely.
hideIconWrapper
boolean
default: false
Hides the icon's background wrapper, keeping the icon itself.
closeButtonProps
Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type">
default: —
Extra props forwarded to the close button.
Motion
| Prop | Type | Default | Description |
|---|---|---|---|
| disableAnimation | boolean | false | Disables the enter/exit animation. |
disableAnimation
boolean
default: false
Disables the enter/exit animation.
Events
| Prop | Type | Default | Description |
|---|---|---|---|
| onClose | () => void | — | Called when the close button is pressed. |
| onVisibleChange | (isVisible: boolean) => void | — | Called whenever visibility changes. |
onClose
() => void
default: —
Called when the close button is pressed.
onVisibleChange
(isVisible: boolean) => void
default: —
Called whenever visibility changes.
Styling
| Prop | Type | Default | Description |
|---|---|---|---|
| classNames | Partial<Record<AlertSlot, string>> | — | Per-slot class overrides. |
| className | string | — | Class applied to the root element. |
| style | CSSProperties | — | Inline styles for the root element. |
classNames
Partial<Record<AlertSlot, string>>
default: —
Per-slot class overrides.
className
string
default: —
Class applied to the root element.
style
CSSProperties
default: —
Inline styles for the root element.
Accessibility
- The root element carries role="alert", so screen readers announce new alerts as soon as they mount without the user needing to navigate to them.
- When isClosable is true, the close button has a built-in aria-label of "Close" and responds to both a click and the Escape key while the alert has focus.
- Color is never the only signal — pair it with a clear title/description, since color alone doesn't communicate anything to a screen-reader user or anyone with color-vision deficiency.
Best practices
- Keep the title short and the description one sentence — Alert is for a quick status update, not an essay.
- Use isClosable={false} for validation errors that are still attached to an invalid field, so the user resolves the actual problem instead of just dismissing the message.
- Reach for variant="soft" inside forms and cards, where a solid block of color competes too hard with the surrounding content.
- Avoid stacking more than two or three Alerts at once — if there are several unrelated issues, consider a single Alert with a list in the description instead.
- For a message that should slide in, sit outside the document flow, and disappear on its own, use Toast instead — Alert stays inline and never auto-dismisses.