Alert
Banner with a colored accent stripe. Body text stays neutral so contrast never depends on the variant.
Storage almost full
You are using 92% of your plan's storage.
Payment failed
Update your card to keep your subscription active.
import { CircleAlert, TriangleAlert } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "@/components/motion/alert";
export function AlertPreview() {
return (
<div className="flex w-full max-w-sm flex-col gap-3">
<Alert variant="warning">
<TriangleAlert aria-hidden="true" className="mt-0.5 h-4 w-4 shrink-0" />
<div>
<AlertTitle>Storage almost full</AlertTitle>
<AlertDescription>You are using 92% of your plan's storage.</AlertDescription>
</div>
</Alert>
<Alert variant="destructive">
<CircleAlert aria-hidden="true" className="mt-0.5 h-4 w-4 shrink-0" />
<div>
<AlertTitle>Payment failed</AlertTitle>
<AlertDescription>Update your card to keep your subscription active.</AlertDescription>
</div>
</Alert>
</div>
);
}
// easeui.dev/components/motion/alert
import type { HTMLAttributes } from "react";
import { cn } from "@/lib/utils";
export type AlertVariant = "neutral" | "success" | "warning" | "destructive";
export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
/** Color of the accent stripe and icon. Default "neutral". */
variant?: AlertVariant;
}
const ACCENT_CLASS: Record<AlertVariant, string> = {
neutral: "border-l-border-strong [&_svg]:text-muted-foreground",
success: "border-l-success [&_svg]:text-success",
warning: "border-l-warning [&_svg]:text-warning",
destructive: "border-l-destructive [&_svg]:text-destructive",
};
/** A banner with a colored accent stripe. Body text stays neutral so contrast never depends on the variant. */
export function Alert({ variant = "neutral", className, ...props }: AlertProps) {
return (
<div
role="alert"
className={cn(
"flex items-start gap-3 rounded-xl border-l-4 bg-card p-4 text-sm shadow-[0_0_0_1px_var(--border)]",
ACCENT_CLASS[variant],
className,
)}
{...props}
/>
);
}
export function AlertTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) {
return (
<h5 className={cn("font-medium leading-tight text-foreground", className)} {...props} />
);
}
export function AlertDescription({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) {
return (
<p className={cn("mt-1 text-pretty text-muted-foreground", className)} {...props} />
);
}
Installation
$ bunx --bun shadcn add @easeui/alert
- 1
Set up the theme tokens
Do this once per project. Follow the theme setup or skip it if you already ran shadcn init.
- 2
Install the dependencies
terminal npm install clsx lucide-react tailwind-merge - 3
Add the source files
components/motion/alert.tsx // easeui.dev/components/motion/alert import type { HTMLAttributes } from "react"; import { cn } from "@/lib/utils"; export type AlertVariant = "neutral" | "success" | "warning" | "destructive"; export interface AlertProps extends HTMLAttributes<HTMLDivElement> { /** Color of the accent stripe and icon. Default "neutral". */ variant?: AlertVariant; } const ACCENT_CLASS: Record<AlertVariant, string> = { neutral: "border-l-border-strong [&_svg]:text-muted-foreground", success: "border-l-success [&_svg]:text-success", warning: "border-l-warning [&_svg]:text-warning", destructive: "border-l-destructive [&_svg]:text-destructive", }; /** A banner with a colored accent stripe. Body text stays neutral so contrast never depends on the variant. */ export function Alert({ variant = "neutral", className, ...props }: AlertProps) { return ( <div role="alert" className={cn( "flex items-start gap-3 rounded-xl border-l-4 bg-card p-4 text-sm shadow-[0_0_0_1px_var(--border)]", ACCENT_CLASS[variant], className, )} {...props} /> ); } export function AlertTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) { return ( <h5 className={cn("font-medium leading-tight text-foreground", className)} {...props} /> ); } export function AlertDescription({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) { return ( <p className={cn("mt-1 text-pretty text-muted-foreground", className)} {...props} /> ); }lib/utils.ts import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) }
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| variant? | "neutral" | "success" | "warning" | "destructive" | neutral | Color of the accent stripe and icon. Default "neutral". |
Updated