import { useStore } from '@nanostores/react' import { type ReactNode, useEffect, useRef, useState } from 'react' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { CopyButton } from '@/components/ui/copy-button' import { triggerHaptic } from '@/lib/haptics' import { AlertCircle, AlertTriangle, CheckCircle2, Info, type LucideIcon, X } from '@/lib/icons' import { cn } from '@/lib/utils' import { $notifications, type AppNotification, clearNotifications, dismissNotification, type NotificationKind } from '@/store/notifications' type ToneVariant = 'default' | 'destructive' | 'warning' | 'success' const tone: Record = { error: { icon: AlertCircle, iconClass: 'text-destructive', variant: 'destructive' }, warning: { icon: AlertTriangle, iconClass: 'text-primary', variant: 'warning' }, info: { icon: Info, iconClass: 'text-muted-foreground', variant: 'default' }, success: { icon: CheckCircle2, iconClass: 'text-primary', variant: 'success' } } const STACK_SURFACE = 'pointer-events-auto border-border/80 bg-popover/95 shadow-lg shadow-black/5 backdrop-blur-md' const GHOST_BTN = 'bg-transparent text-muted-foreground hover:text-foreground' export function NotificationStack() { const notifications = useStore($notifications) const lastNotificationIdRef = useRef(null) const [expanded, setExpanded] = useState(false) useEffect(() => { if (notifications.length <= 1) { setExpanded(false) } }, [notifications.length]) useEffect(() => { const latest = notifications[0] if (!latest || latest.id === lastNotificationIdRef.current) { return } lastNotificationIdRef.current = latest.id if (latest.kind === 'success') { triggerHaptic('success') } else if (latest.kind === 'error') { triggerHaptic('error') } else if (latest.kind === 'warning') { triggerHaptic('warning') } }, [notifications]) if (notifications.length === 0) { return null } const [latest, ...olderNotifications] = notifications const overflowCount = olderNotifications.length return (
{expanded && olderNotifications.map(n => )} {overflowCount > 0 && (
)}
) } function NotificationItem({ notification }: { notification: AppNotification }) { const styles = tone[notification.kind] const Icon = styles.icon const hasDetail = Boolean(notification.detail && notification.detail !== notification.message) return (
{notification.title && {notification.title}}

{notification.message}

{hasDetail && }
) } function NotificationDetail({ detail }: { detail: string }) { return (
Details
          {detail}
        
Copy detail
) } export function InlineNotice({ kind = 'info', title, children, className }: { kind?: NotificationKind title?: string children: ReactNode className?: string }) { const styles = tone[kind] const Icon = styles.icon return ( {title && {title}} {children} ) }