UI/UI
Alert
A versatile alert component for displaying important messages, notifications, and status updates.
Default Alert: This is a basic alert message.
Error: Something went wrong. Please try again.
Warning: This action cannot be undone.
Success: Your changes have been saved.
Info: New features are now available.
<div className="space-y-4">
<Alert>This is a basic alert message.</Alert>
<Alert variant="destructive">
Something went wrong. Please try again.
</Alert>
<Alert variant="warning">This action cannot be undone.</Alert>
<Alert variant="success">Your changes have been saved.</Alert>
<Alert variant="info">New features are now available.</Alert>
</div>
Installation
Install following dependencies:
npm install class-variance-authority lucide-react motion
pnpm add class-variance-authority lucide-react motion
yarn add class-variance-authority lucide-react motion
bun add class-variance-authority lucide-react motion
Copy and paste the following code into your project.
"use client";
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { type LucideIcon, X } from "lucide-react";
import { motion, AnimatePresence } from "motion/react";
const alertVariants = cva(
"relative w-full rounded-lg border p-4 text-sm transition-colors",
{
variants: {
variant: {
default:
"border-[hsl(var(--hu-border))] bg-[hsl(var(--hu-card))] text-[hsl(var(--hu-card-foreground))]",
destructive:
"border-[hsl(var(--hu-destructive))] bg-[hsl(var(--hu-destructive))]/10 text-[hsl(var(--hu-destructive))] [&>svg]:text-[hsl(var(--hu-destructive))]",
warning:
"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-700 dark:bg-amber-950/30 dark:text-amber-200 [&>svg]:text-amber-600 dark:[&>svg]:text-amber-400",
success:
"border-green-200 bg-green-50 text-green-800 dark:border-green-700 dark:bg-green-950/30 dark:text-green-200 [&>svg]:text-green-600 dark:[&>svg]:text-green-400",
info: "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-700 dark:bg-blue-950/30 dark:text-blue-200 [&>svg]:text-blue-600 dark:[&>svg]:text-blue-400",
},
},
defaultVariants: {
variant: "default",
},
},
);
export interface AlertProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof alertVariants> {
icon?: LucideIcon;
title?: string;
dismissible?: boolean;
onDismiss?: () => void;
}
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
(
{
className,
variant,
icon: Icon,
title,
dismissible,
onDismiss,
children,
...props
},
ref,
) => {
const [isVisible, setIsVisible] = React.useState(true);
const handleDismiss = () => {
setIsVisible(false);
setTimeout(() => {
onDismiss?.();
}, 150); // Match the exit animation duration
};
// Extract motion-conflicting props
const {
onDrag,
onDragStart,
onDragEnd,
onAnimationStart,
onAnimationEnd,
onAnimationIteration,
onTransitionEnd,
...motionProps
} = props;
return (
<AnimatePresence>
{isVisible && (
<motion.div
ref={ref}
className={cn(alertVariants({ variant }), className)}
initial={{ opacity: 0, y: -10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: -10, scale: 0.95 }}
transition={{ duration: 0.15, ease: "easeOut" }}
role="alert"
{...motionProps}
>
<div className="flex">
{Icon && (
<div className="flex-shrink-0">
<Icon className="h-4 w-4 mt-0.5" />
</div>
)}
<div className={cn("flex-1", Icon && "ml-3")}>
{title && <h3 className="text-sm font-medium mb-1">{title}</h3>}
<div
className={cn("text-sm", title && "text-muted-foreground")}
>
{children}
</div>
</div>
{dismissible && (
<div className="flex-shrink-0 ml-3">
<button
type="button"
className="inline-flex rounded-md p-1.5 transition-colors hover:bg-black/5 dark:hover:bg-white/5 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[hsl(var(--hu-ring))]"
onClick={handleDismiss}
aria-label="Dismiss alert"
>
<X className="h-4 w-4" />
</button>
</div>
)}
</div>
</motion.div>
)}
</AnimatePresence>
);
},
);
Alert.displayName = "Alert";
export { Alert, alertVariants };
"use client";
import { Alert, type AlertProps } from "../alert";
import { type LucideIcon } from "lucide-react";
import {
AlertTriangle,
CheckCircle,
Info,
X,
AlertCircle,
Shield,
Bell,
Star,
Zap,
Heart,
Settings,
User,
Mail,
Server,
CreditCard,
Trophy,
HardDrive,
} from "lucide-react";
// Map of icon names to actual components
const iconMap = {
AlertTriangle,
CheckCircle,
Info,
X,
AlertCircle,
Shield,
Bell,
Star,
Zap,
Heart,
Settings,
User,
Mail,
Server,
CreditCard,
Trophy,
HardDrive,
} as const;
export type IconName = keyof typeof iconMap;
interface AlertWithIconProps extends Omit<AlertProps, "icon"> {
iconName?: IconName;
icon?: LucideIcon;
}
export function AlertWithIcon({
iconName,
icon,
...props
}: AlertWithIconProps) {
// Priority: custom icon > iconName > no icon
let IconComponent: LucideIcon | undefined;
if (icon) {
IconComponent = icon;
} else if (iconName) {
IconComponent = iconMap[iconName];
}
return <Alert icon={IconComponent} {...props} />;
}
npx hextaui@latest add alert
pnpm dlx hextaui@latest add alert
yarn dlx hextaui@latest add alert
bun x hextaui@latest add alert
Usage
import { Alert, AlertWithIcon } from "@/components/ui/alert";
import { Database, Rocket } from "lucide-react";
Basic Alert
<Alert variant="default">This is a default alert.</Alert>
<Alert variant="destructive">This is a destructive alert.</Alert>
<Alert variant="warning">This is a warning alert.</Alert>
<Alert variant="success">This is a success alert.</Alert>
<Alert variant="info">This is an info alert.</Alert>
Alert with Predefined Icons
<AlertWithIcon iconName="Info" variant="info" title="Information">
This uses a predefined icon from the available icon set.
</AlertWithIcon>
Alert with Custom Icons
<AlertWithIcon icon={Database} variant="warning" title="Database Alert">
This uses a custom Lucide icon component for maximum flexibility.
</AlertWithIcon>
Examples
Variants
Default Alert: This is a basic alert message.
Error: Something went wrong. Please try again.
Warning: This action cannot be undone.
Success: Your changes have been saved.
Info: New features are now available.
<div className="space-y-4">
<Alert>
<strong>Default Alert:</strong> This is a basic alert message.
</Alert>
<Alert variant="destructive">
<strong>Error:</strong> Something went wrong. Please try again.
</Alert>
<Alert variant="warning">
<strong>Warning:</strong> This action cannot be undone.
</Alert>
<Alert variant="success">
<strong>Success:</strong> Your changes have been saved.
</Alert>
<Alert variant="info">
<strong>Info:</strong> New features are now available.
</Alert>
</div>
With Titles
System Update
A new version of the application is available. Please restart to apply updates.
Connection Failed
Unable to connect to the server. Please check your internet connection.
Data Loss Warning
You have unsaved changes. Leaving this page will discard your work.
Upload Complete
Your files have been successfully uploaded to the cloud storage.
Feature Preview
Try out our new dashboard features in beta mode.
<div className="space-y-4">
<Alert title="System Update">
A new version of the application is available. Please restart to apply
updates.
</Alert>
<Alert variant="destructive" title="Connection Failed">
Unable to connect to the server. Please check your internet connection.
</Alert>
<Alert variant="warning" title="Data Loss Warning">
You have unsaved changes. Leaving this page will discard your work.
</Alert>
<Alert variant="success" title="Upload Complete">
Your files have been successfully uploaded to the cloud storage.
</Alert>
<Alert variant="info" title="Feature Preview">
Try out our new dashboard features in beta mode.
</Alert>
</div>
With Icons
New Features Available
We've added new collaboration tools to help you work better with your team.
Payment Successful
Your subscription has been renewed for another year.
Storage Almost Full
You've used 95% of your storage space. Consider upgrading your plan.
Action Failed
Could not complete the requested action. Please try again later.
Network Connected
You are now connected to the secure network.
Database Backup Required
It's been 7 days since your last backup. Consider backing up your data.
Deployment Successful
Your application has been deployed to production successfully.
Break Time
You've been coding for 2 hours. Time for a coffee break!
import { AlertWithIcon } from "@/components/ui/Alert";
import { Wifi, Database, Rocket, Coffee } from "lucide-react";
<div className="space-y-4">
{/* Using predefined icon names */}
<AlertWithIcon
iconName="Info"
variant="info"
title="New Features Available"
>
We've added new collaboration tools to help you work better with your team.
</AlertWithIcon>
<AlertWithIcon
iconName="CheckCircle"
variant="success"
title="Payment Successful"
>
Your subscription has been renewed for another year.
</AlertWithIcon>
{/* Using custom icon components */}
<AlertWithIcon
icon={Wifi}
variant="info"
title="Network Connected"
>
You are now connected to the secure network.
</AlertWithIcon>
<AlertWithIcon
icon={Database}
variant="warning"
title="Database Backup Required"
>
It's been 7 days since your last backup. Consider backing up your data.
</AlertWithIcon>
<AlertWithIcon
icon={Rocket}
variant="success"
title="Deployment Successful"
>
Your application has been deployed to production successfully.
</AlertWithIcon>
</div>
With Custom Icons
Code Review Ready
Your pull request is ready for code review by the team.
Feature Unlocked
Congratulations! You've unlocked premium features.
Performance Improved
Your application performance has increased by 40% this month.
Security Alert
We detected unusual login activity. Please verify your account.
Meeting Reminder
Your team standup meeting starts in 15 minutes.
import { AlertWithIcon } from "@/components/ui/Alert";
import { Code, Sparkles, TrendingUp, Lock, Calendar } from "lucide-react";
<div className="space-y-4">
<AlertWithIcon
icon={Code}
variant="info"
title="Code Review Ready"
>
Your pull request is ready for code review by the team.
</AlertWithIcon>
<AlertWithIcon
icon={Sparkles}
variant="success"
title="Feature Unlocked"
>
Congratulations! You've unlocked premium features.
</AlertWithIcon>
<AlertWithIcon
icon={TrendingUp}
variant="info"
title="Performance Improved"
>
Your application performance has increased by 40% this month.
</AlertWithIcon>
<AlertWithIcon
icon={Lock}
variant="warning"
title="Security Alert"
>
We detected unusual login activity. Please verify your account.
</AlertWithIcon>
<AlertWithIcon
icon={Calendar}
variant="default"
title="Meeting Reminder"
>
Your team standup meeting starts in 15 minutes.
</AlertWithIcon>
</div>
Dismissible Alerts
Notification
You have 3 new messages in your inbox.
Achievement Unlocked
Congratulations! You've completed 100 tasks this month.
Storage Warning
Your storage is almost full. Consider upgrading your plan.
Thank You!
Thank you for being an awesome user! Your feedback helps us improve.
import { Bell, Trophy, HardDrive } from "lucide-react";
<div className="space-y-4">
<Alert
icon={Bell}
variant="info"
title="Notification"
dismissible
onDismiss={() => console.log("Alert dismissed")}
>
You have 3 new messages in your inbox.
</Alert>
<Alert
icon={Trophy}
variant="success"
title="Achievement Unlocked"
dismissible
onDismiss={() => console.log("Achievement dismissed")}
>
Congratulations! You've completed 100 tasks this month.
</Alert>
<Alert
icon={HardDrive}
variant="warning"
title="Storage Warning"
dismissible
onDismiss={() => console.log("Storage warning dismissed")}
>
Your storage is almost full. Consider upgrading your plan.
</Alert>
</div>
Custom Styling
Rounded Alert: Custom border radius styling.
Dashed Border: Alert with dashed border style.
With Shadow: Alert with enhanced shadow.
Gradient Background: Custom gradient styling.
<div className="space-y-4">
<Alert className="rounded-xl border-2">
<strong>Rounded Alert:</strong> Custom border radius styling.
</Alert>
<Alert variant="info" className="border-dashed">
<strong>Dashed Border:</strong> Alert with dashed border style.
</Alert>
<Alert variant="success" className="shadow-lg">
<strong>With Shadow:</strong> Alert with enhanced shadow.
</Alert>
<Alert className="bg-gradient-to-r from-purple-50 to-pink-50 border-purple-200 text-purple-800 dark:from-purple-950/20 dark:to-pink-950/20 dark:border-purple-800 dark:text-purple-200">
<strong>Gradient Background:</strong> Custom gradient styling.
</Alert>
</div>
Real-world Examples
System Status
All Systems Operational
All services are running normally. Last updated 2 minutes ago.
Account Security
Password Expiring Soon
Your password will expire in 3 days. Update it now to maintain account security.
Billing Information
Payment Method Required
Your trial ends in 2 days. Add a payment method to continue using our services.
import { Server, Shield, CreditCard } from "lucide-react";
<div className="space-y-4">
<div className="space-y-2">
<h4 className="text-sm font-medium">System Status</h4>
<Alert icon={Server} variant="success" title="All Systems Operational">
All services are running normally. Last updated 2 minutes ago.
</Alert>
</div>
<div className="space-y-2">
<h4 className="text-sm font-medium">Account Security</h4>
<Alert icon={Shield} variant="warning" title="Password Expiring Soon">
Your password will expire in 3 days. Update it now to maintain account security.
</Alert>
</div>
<div className="space-y-2">
<h4 className="text-sm font-medium">Billing Information</h4>
<Alert icon={CreditCard} variant="destructive" title="Payment Method Required">
Your trial ends in 2 days. Add a payment method to continue using our services.
</Alert>
</div>
</div>
Props
Alert Props
Prop | Type | Default |
---|---|---|
children? | ReactNode | undefined |
className? | string | undefined |
onDismiss? | () => void | undefined |
dismissible? | boolean | false |
title? | string | undefined |
icon? | LucideIcon | undefined |
variant? | "default" | "destructive" | "warning" | "success" | "info" | "default" |
AlertWithIcon Props
The AlertWithIcon
component extends all the base Alert
props and adds icon-specific functionality:
Prop | Type | Default |
---|---|---|
icon? | LucideIcon | undefined |
iconName? | "AlertTriangle" | "CheckCircle" | "Info" | "X" | "AlertCircle" | "Shield" | "Bell" | "Star" | "Zap" | "Heart" | "Settings" | "User" | "Mail" | "Server" | "CreditCard" | "Trophy" | "HardDrive" | undefined |
Icon Priority: When both icon
and iconName
are provided, the custom icon
prop takes precedence over iconName
.
Edit on GitHub
Last updated on