Displays a callout for user attention.
Installation
npx shadcn@latest add @caprice/alertnpm install @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, type VariantProps } from 'cva';import { twMerge } from 'tailwind-merge';export const { compose, cva, cx: cn,} = defineConfig({ hooks: { onComplete: (className: string) => twMerge(className), },});export type { VariantProps };Copy and paste the following code into your project.
import { mergeProps, useRender } from '@base-ui/react';import { cn, cva, type VariantProps } from '@/lib/utils';const alertVariants = cva({ base: 'relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-xl border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:text-current', variants: { size: { xs: 'text-sm [&>svg]:translate-y-0.5', sm: 'text-sm *:data-[slot="alert-title"]:text-base [&>svg]:translate-y-1', md: 'text-base *:data-[slot="alert-title"]:text-xl [&>svg]:translate-y-1.5', }, variant: { default: 'bg-card text-card-foreground', success: 'border-success/30 bg-success/5 [&>svg]:text-success', info: 'border-info/30 bg-info/5 [&>svg]:text-info', warning: 'border-warning/30 bg-warning/5 [&>svg]:text-warning', destructive: 'border-destructive/30 bg-destructive/5 [&>svg]:text-destructive', }, }, defaultVariants: { size: 'sm', variant: 'default', },});export namespace Root { export type Variants = { /** * Size * @default 'sm' */ size?: VariantProps<typeof alertVariants>['size']; /** * Variant * @default 'default' */ variant?: VariantProps<typeof alertVariants>['variant']; }; export type Props = useRender.ComponentProps<'div'> & Root.Variants;}/** * A component that displays a message to the user. * Renders a `<div>` element. * * Documentation: [Caprice UI Alert](https://caprice-ui.com/docs/components/alert) */export function Root({ className, size, render, variant, ...props }: Root.Props) { const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = { 'data-slot': 'alert', role: 'alert', className: alertVariants({ variant, size, className }), }; return useRender({ defaultTagName: 'div', render, props: mergeProps<'div'>(defaultProps, props), });}/** * A component that displays the title of the alert. * Renders a `<div>` element. * * Documentation: [Caprice UI Alert](https://caprice-ui.com/docs/components/alert) */export namespace Title { export type Props = useRender.ComponentProps<'div'>;}export function Title({ className, render, ...props }: Title.Props) { const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = { 'data-slot': 'alert-title', className: cn('col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight', className), }; return useRender({ defaultTagName: 'div', render, props: mergeProps<'div'>(defaultProps, props), });}/** * A component that displays the description of the alert. * Renders a `<div>` element. * * Documentation: [Caprice UI Alert](https://caprice-ui.com/docs/components/alert) */export namespace Description { export type Props = useRender.ComponentProps<'div'>;}export function Description({ className, render, ...props }: Description.Props) { const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = { 'data-slot': 'alert-description', className: cn( 'col-start-2 grid justify-items-start gap-1 text-muted-foreground text-sm [&_p]:leading-relaxed', className ), }; return useRender({ defaultTagName: 'div', render, props: mergeProps<'div'>(defaultProps, props), });}Update the import paths to match your project setup.
Usage
import * as Alert from "@/components/caprice-ui/alert"import * as Alert from "@caprice-ui/react/alert"<Alert.Root>
<CheckCircle2Icon />
<Alert.Title>Success! Your changes have been saved</Alert.Title>
<Alert.Description>This is an alert with icon, title and description.</Alert.Description>
</Alert.Root>Examples
Icon
info
Warning
Success
Destructive
Dismissible
Custom
Differences with shadcn/ui / Radix
If you're familiar with Radix UI and shadcn/ui, most patterns will carry over. This guide points out the differences so you can start using Caprice UI without surprises.
Key changes
| Feature | shadcn/ui | Caprice UI |
|---|---|---|
| Primitive | Native <div> elements | Base UI useRender + native <div> |
| Composition | None | render prop |
| API pattern | Flat exports (Alert, AlertTitle) | Namespace pattern (Alert.Root, Alert.Title) |
| Variants | default, destructive | default, success, info, warning, destructive |
| Border radius | rounded-lg | rounded-xl |
| Destructive style | text-destructive bg-card | border-destructive/30 bg-destructive/5 with icon coloring |
| Semantic colors | Not included | success, info, warning with opacity-based bg/border |
Comparison Example
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>Something went wrong.</AlertDescription>
</Alert><Alert.Root variant="destructive">
<AlertCircle />
<Alert.Title>Error</Alert.Title>
<Alert.Description>Something went wrong.</Alert.Description>
</Alert.Root>Accessibility
- Live region: The component uses
role="alert"which creates an ARIA live region with implicitaria-live="assertive"andaria-atomic="true". Screen readers announce the alert content immediately when it appears in the DOM. - Use sparingly: Because alerts interrupt the user's workflow, reserve them for important, time-sensitive information. Overusing alerts can frustrate users and diminish their effectiveness.
- Don't rely on color alone: Each variant (success, warning, destructive, info) should be paired with an icon and descriptive text. The component automatically colors icons to match the variant, but the message content should make the alert's purpose clear without color.
- Dismissible alerts: When using a dismiss button, ensure it has an accessible name (e.g.,
aria-label="Dismiss alert") and is keyboard accessible. - No focus management: Alerts don't automatically receive focus—this is intentional per WAI-ARIA guidelines. If the alert requires user action, consider using an Alert Dialog instead.
- Dynamic alerts: For alerts that appear after user interaction (e.g., form validation), the live region ensures the message is announced. Avoid removing alerts too quickly; give users time to read and comprehend the content.
Variants
Prop
Type
API Reference
Root
Prop
Type
Title
Prop
Type
Description
Prop
Type