74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import * as React from 'react';
|
|
import { AlertCircle, CheckCircle2, AlertTriangle, Info } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
variant?: 'default' | 'info' | 'success' | 'warning' | 'destructive';
|
|
icon?: React.ReactNode;
|
|
}
|
|
|
|
const variantMap = {
|
|
default: 'bg-background text-foreground border-border',
|
|
info: 'bg-sky-50 dark:bg-sky-950/30 text-sky-900 dark:text-sky-200 border-sky-200 dark:border-sky-800',
|
|
success: 'bg-emerald-50 dark:bg-emerald-950/30 text-emerald-900 dark:text-emerald-200 border-emerald-200 dark:border-emerald-800',
|
|
warning: 'bg-amber-50 dark:bg-amber-950/30 text-amber-900 dark:text-amber-200 border-amber-200 dark:border-amber-800',
|
|
destructive: 'bg-rose-50 dark:bg-rose-950/30 text-rose-900 dark:text-rose-200 border-rose-200 dark:border-rose-800',
|
|
};
|
|
|
|
const defaultIcons = {
|
|
default: <Info className="h-5 w-5 text-primary" />,
|
|
info: <Info className="h-5 w-5 text-sky-600 dark:text-sky-400" />,
|
|
success: <CheckCircle2 className="h-5 w-5 text-emerald-600 dark:text-emerald-400" />,
|
|
warning: <AlertTriangle className="h-5 w-5 text-amber-600 dark:text-amber-400" />,
|
|
destructive: <AlertCircle className="h-5 w-5 text-rose-600 dark:text-rose-400" />,
|
|
};
|
|
|
|
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|
({ className, variant = 'default', icon, children, ...props }, ref) => {
|
|
const displayIcon = icon !== undefined ? icon : defaultIcons[variant];
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
role="alert"
|
|
className={cn(
|
|
'relative w-full rounded-xl border p-4 flex gap-3 items-start shadow-subtle',
|
|
variantMap[variant],
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{displayIcon && <div className="shrink-0 mt-0.5">{displayIcon}</div>}
|
|
<div className="flex-1 flex flex-col gap-1">{children}</div>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
Alert.displayName = 'Alert';
|
|
|
|
const AlertTitle = React.forwardRef<
|
|
HTMLParagraphElement,
|
|
React.HTMLAttributes<HTMLHeadingElement>
|
|
>(({ className, ...props }, ref) => (
|
|
<h5
|
|
ref={ref}
|
|
className={cn('font-semibold text-sm leading-tight tracking-tight', className)}
|
|
{...props}
|
|
/>
|
|
));
|
|
AlertTitle.displayName = 'AlertTitle';
|
|
|
|
const AlertDescription = React.forwardRef<
|
|
HTMLParagraphElement,
|
|
React.HTMLAttributes<HTMLParagraphElement>
|
|
>(({ className, ...props }, ref) => (
|
|
<div
|
|
ref={ref}
|
|
className={cn('text-xs opacity-90 leading-relaxed [&_p]:leading-relaxed', className)}
|
|
{...props}
|
|
/>
|
|
));
|
|
AlertDescription.displayName = 'AlertDescription';
|
|
|
|
export { Alert, AlertTitle, AlertDescription };
|