Files
krow-demo/src/components/ds/Alert.jsx
2026-08-07 23:53:15 +05:30

72 lines
2.3 KiB
JavaScript

import * as React from 'react';
import { AlertCircle, CheckCircle2, Info, TriangleAlert, X } from 'lucide-react';
import { cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const alertVariants = cva('flex items-start gap-3 rounded-xl border p-4 animate-slide-down', {
variants: {
tone: {
info: 'bg-info-muted border-krow-blue/20 text-ink-2',
success: 'bg-success-muted border-success/20 text-ink-2',
warning: 'bg-warning-muted border-warning/25 text-ink-2',
destructive: 'bg-destructive-muted border-destructive/20 text-ink-2',
neutral: 'bg-surface-subtle border-border text-ink-2',
},
},
defaultVariants: { tone: 'info' },
});
const ICONS = {
info: Info,
success: CheckCircle2,
warning: TriangleAlert,
destructive: AlertCircle,
neutral: Info,
};
const ICON_COLORS = {
info: 'text-krow-blue',
success: 'text-success',
warning: 'text-warning',
destructive: 'text-destructive',
neutral: 'text-ink-4',
};
/**
* Alert — an inline, persistent message about the state of the page.
*
* For transient confirmation of something the user just did, use `toast`
* instead: an Alert that appears and disappears is easy to miss, and a toast
* that persists is noise.
*/
export function Alert({ tone = 'info', title, children, icon, onDismiss, action, className, ...props }) {
const Icon = icon || ICONS[tone];
return (
<div role="alert" className={cn(alertVariants({ tone }), className)} {...props}>
{Icon && <Icon className={cn('w-4.5 h-4.5 shrink-0 mt-0.5', ICON_COLORS[tone])} aria-hidden="true" />}
<div className="flex-1 min-w-0">
{title && <p className="text-body-sm font-semibold text-ink-1">{title}</p>}
{children && (
<div className={cn('text-body-sm text-ink-2 leading-relaxed', title && 'mt-0.5')}>
{children}
</div>
)}
{action && <div className="mt-3">{action}</div>}
</div>
{onDismiss && (
<button
type="button"
onClick={onDismiss}
aria-label="Dismiss"
className="grid place-items-center w-6 h-6 rounded-md text-ink-4 hover:text-ink-1 hover:bg-black/5 transition-colors shrink-0 focus-ring-inset"
>
<X className="w-3.5 h-3.5" aria-hidden="true" />
</button>
)}
</div>
);
}