From 59eaa342a9de2f3f0fedbae850a864951f1cfde3 Mon Sep 17 00:00:00 2001 From: Knacky Date: Sun, 21 Jun 2026 22:11:10 +0200 Subject: [PATCH] feat(frontend): add AlertBanner component + 4 semantic variants border-l-4 semantic strip, bg-paper, Lucide icons at size=16. ARIA role="alert" for error/warn, role="status" for success/info. No shadow, no radius, no transition. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/AlertBanner.tsx | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 frontend/src/components/AlertBanner.tsx diff --git a/frontend/src/components/AlertBanner.tsx b/frontend/src/components/AlertBanner.tsx new file mode 100644 index 0000000..14af0d7 --- /dev/null +++ b/frontend/src/components/AlertBanner.tsx @@ -0,0 +1,30 @@ +import type { ReactNode } from 'react'; +import { AlertCircle, AlertTriangle, CheckCircle, Info } from 'lucide-react'; + +type AlertVariant = 'error' | 'warn' | 'success' | 'info'; + +interface AlertBannerProps { + variant: AlertVariant; + title?: string; + children: ReactNode; +} + +const CONFIG: Record = { + error: { cls: 'alert-error', Icon: AlertCircle, role: 'alert' }, + warn: { cls: 'alert-warn', Icon: AlertTriangle, role: 'alert' }, + success: { cls: 'alert-success', Icon: CheckCircle, role: 'status' }, + info: { cls: 'alert-info', Icon: Info, role: 'status' }, +}; + +export function AlertBanner({ variant, title, children }: AlertBannerProps): JSX.Element { + const { cls, Icon, role } = CONFIG[variant]; + return ( +
+ +
+ {title ? {title} : null} + {children} +
+
+ ); +}