Some checks failed
Pull Request Checks / Code Quality & Security (push) Has been cancelled
Security Audit / Security Vulnerability Audit (push) Has been cancelled
Security Audit / Dependency Review (push) Has been cancelled
Security Audit / CodeQL Security Analysis (push) Has been cancelled
Security Audit / Check Outdated Dependencies (push) Has been cancelled
- Migrate all molecule components (DataTable, PaginationBar, FilterDropdown, AlertBanner, FormField, SectionCard, SubCard, MetricCard, AnimatedCard, OtpInput) to shadcn/ui primitives with legacy backups and comparison stories - Install 24 shadcn/ui primitives (accordion, alert, badge, button, card, checkbox, collapsible, dialog, dropdown-menu, input-otp, input, label, pagination, popover, radio-group, select, separator, sheet, skeleton, table, tabs, toggle-group, toggle, tooltip) with barrel exports - Replace 69 raw HTML elements across all features with shadcn components: 35+ <button> → Button, 5 <select> → Select, 15+ <label> → Label, 6 <input type=checkbox> → Checkbox, 7 <input type=radio> → RadioGroup - Add TextRotate animation component and integrate into hero section with rotating service names (Internet, Phone Plans, VPN, IT Support, Business) - Add destructive color token aliases for error state consistency - Add CLAUDE.md rules for shadcn migration process Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
109 lines
2.6 KiB
TypeScript
109 lines
2.6 KiB
TypeScript
"use client";
|
||
|
||
import React from "react";
|
||
import {
|
||
CheckCircleIcon,
|
||
InformationCircleIcon,
|
||
ExclamationTriangleIcon,
|
||
XCircleIcon,
|
||
} from "@heroicons/react/24/outline";
|
||
|
||
type Variant = "success" | "info" | "warning" | "error";
|
||
type IconType = React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
||
|
||
const variantClasses: Record<
|
||
Variant,
|
||
{ bg: string; border: string; text: string; icon: string; Icon: IconType }
|
||
> = {
|
||
success: {
|
||
bg: "bg-success-soft",
|
||
border: "border-success/30",
|
||
text: "text-success",
|
||
icon: "text-success",
|
||
Icon: CheckCircleIcon,
|
||
},
|
||
info: {
|
||
bg: "bg-info-soft",
|
||
border: "border-info/30",
|
||
text: "text-info",
|
||
icon: "text-info",
|
||
Icon: InformationCircleIcon,
|
||
},
|
||
warning: {
|
||
bg: "bg-warning-soft",
|
||
border: "border-warning/35",
|
||
text: "text-foreground",
|
||
icon: "text-warning",
|
||
Icon: ExclamationTriangleIcon,
|
||
},
|
||
error: {
|
||
bg: "bg-danger-soft",
|
||
border: "border-danger/30",
|
||
text: "text-danger",
|
||
icon: "text-danger",
|
||
Icon: XCircleIcon,
|
||
},
|
||
};
|
||
|
||
interface AlertBannerProps extends React.HTMLAttributes<HTMLDivElement> {
|
||
variant?: Variant;
|
||
title?: string;
|
||
children?: React.ReactNode;
|
||
icon?: React.ReactNode;
|
||
size?: "sm" | "md";
|
||
elevated?: boolean;
|
||
onClose?: () => void;
|
||
}
|
||
|
||
export function AlertBanner({
|
||
variant = "info",
|
||
title,
|
||
children,
|
||
icon,
|
||
size = "md",
|
||
elevated = false,
|
||
onClose,
|
||
className,
|
||
...rest
|
||
}: AlertBannerProps) {
|
||
const styles = variantClasses[variant];
|
||
const Icon = styles.Icon;
|
||
const padding = size === "sm" ? "p-3" : "p-4";
|
||
const radius = "rounded-xl";
|
||
const shadow = elevated ? "shadow-sm" : "";
|
||
const role = variant === "error" || variant === "warning" ? "alert" : "status";
|
||
|
||
return (
|
||
<div
|
||
className={[radius, padding, "border", shadow, styles.bg, styles.border, className]
|
||
.filter(Boolean)
|
||
.join(" ")}
|
||
role={role}
|
||
{...rest}
|
||
>
|
||
<div className="flex items-start gap-3">
|
||
<div className="mt-0.5 flex-shrink-0">
|
||
{icon ? icon : <Icon className={["h-5 w-5", styles.icon].join(" ")} />}
|
||
</div>
|
||
<div className="flex-1">
|
||
{title && <p className={["font-medium", styles.text].join(" ")}>{title}</p>}
|
||
{children && (
|
||
<div className={["text-sm mt-1 text-foreground/80"].join(" ")}>{children}</div>
|
||
)}
|
||
</div>
|
||
{onClose && (
|
||
<button
|
||
onClick={onClose}
|
||
aria-label="Close alert"
|
||
className="text-muted-foreground hover:text-foreground transition-colors"
|
||
>
|
||
×
|
||
</button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export type { AlertBannerProps };
|