Files
design-system/src/components/Icon.tsx
T
2026-09-12 20:29:38 +02:00

139 lines
2.6 KiB
TypeScript

import type { ComponentType, SVGProps } from 'react'
import {
Search,
Sun,
Moon,
Copy,
Check,
Eye,
ArrowRight,
ArrowLeft,
Menu,
Layers,
Sparkles,
Terminal,
AlertTriangle,
AlertCircle,
Info,
CheckCircle2,
X,
Plus,
Minus,
Trash2,
ExternalLink,
ChevronDown,
ChevronRight,
ChevronLeft,
ChevronUp,
Filter,
SlidersHorizontal,
Code2,
Cpu,
Database,
User,
Shield,
Folder,
FileText,
Calendar,
Clock,
RefreshCw,
Download,
Upload,
Settings,
HelpCircle,
type LucideIcon,
type LucideProps,
} from 'lucide-react'
export type { LucideIcon, LucideProps }
const iconMap: Record<string, LucideIcon> = {
// Northstar legacy shorthands
search: Search,
sun: Sun,
moon: Moon,
copy: Copy,
check: Check,
eye: Eye,
arrow: ArrowRight,
'arrow-right': ArrowRight,
'arrow-left': ArrowLeft,
menu: Menu,
layers: Layers,
sparkle: Sparkles,
sparkles: Sparkles,
terminal: Terminal,
// Common UI primitives
close: X,
x: X,
plus: Plus,
minus: Minus,
trash: Trash2,
'trash-2': Trash2,
settings: Settings,
filter: Filter,
sliders: SlidersHorizontal,
refresh: RefreshCw,
download: Download,
upload: Upload,
external: ExternalLink,
'external-link': ExternalLink,
info: Info,
warning: AlertTriangle,
'alert-triangle': AlertTriangle,
alert: AlertCircle,
'alert-circle': AlertCircle,
'check-circle': CheckCircle2,
help: HelpCircle,
'chevron-down': ChevronDown,
'chevron-right': ChevronRight,
'chevron-left': ChevronLeft,
'chevron-up': ChevronUp,
code: Code2,
cpu: Cpu,
database: Database,
user: User,
shield: Shield,
folder: Folder,
file: FileText,
calendar: Calendar,
clock: Clock,
}
export type IconName = keyof typeof iconMap | string
export type IconProps = Omit<SVGProps<SVGSVGElement>, 'ref'> & {
name?: IconName
icon?: LucideIcon | ComponentType<{ size?: number | string; strokeWidth?: number; className?: string }>
size?: number | string
strokeWidth?: number
className?: string
}
/**
* Universal Icon component backed by lucide-react.
* Accepts either a shorthand name (e.g. name="sparkle", name="check")
* or a direct Lucide icon component (e.g. icon={Sparkles}).
*/
export function Icon({
name,
icon: IconComponent,
size = 18,
strokeWidth = 1.8,
className,
...props
}: IconProps) {
const Component = IconComponent || (name ? iconMap[name.toLowerCase()] : undefined) || Layers
return (
<Component
size={size}
strokeWidth={strokeWidth}
className={className}
aria-hidden="true"
{...props}
/>
)
}