feat(icons): add Lucide icon foundation
Add @lucide/angular dependency and a single shared entry point for every icon in the app: app-icon (src/app/shared/ui/icon), backed by a canonical name -> Lucide-icon registry (icon-registry.ts) covering every concept the RC icon audit needs across storefront, builder, and backoffice. One name per meaning, one default size/stroke-width, so every screen renders the same icon the same way. Package note: lucide-angular (unscoped) is deprecated upstream in favor of @lucide/angular - installed the maintained package directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
14
package-lock.json
generated
14
package-lock.json
generated
@@ -17,6 +17,7 @@
|
||||
"@angular/platform-browser": "21.1.5",
|
||||
"@angular/router": "21.1.5",
|
||||
"@angular/service-worker": "21.1.5",
|
||||
"@lucide/angular": "^1.25.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"primeng": "^21.0.3",
|
||||
"rxjs": "~7.8.0",
|
||||
@@ -2009,6 +2010,19 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@lucide/angular": {
|
||||
"version": "1.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@lucide/angular/-/angular-1.25.0.tgz",
|
||||
"integrity": "sha512-Hu1eHlGIeyamhSCFEO5YmiUlWn/h4y9BOXMDndY0HRu05CNeCt5BENkfBoeE/bzggMGGbYG+SOBkQUG939tFXw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=17.0.0",
|
||||
"@angular/core": ">=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"@angular/platform-browser": "21.1.5",
|
||||
"@angular/router": "21.1.5",
|
||||
"@angular/service-worker": "21.1.5",
|
||||
"@lucide/angular": "^1.25.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"primeng": "^21.0.3",
|
||||
"rxjs": "~7.8.0",
|
||||
|
||||
162
src/app/shared/ui/icon/icon-registry.ts
Normal file
162
src/app/shared/ui/icon/icon-registry.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import {
|
||||
LucideAlignLeft as AlignLeft,
|
||||
LucideArrowDown as ArrowDown,
|
||||
LucideArrowLeft as ArrowLeft,
|
||||
LucideArrowRight as ArrowRight,
|
||||
LucideArrowUp as ArrowUp,
|
||||
LucideBadgeCheck as BadgeCheck,
|
||||
LucideBarChart3 as BarChart3,
|
||||
LucideBell as Bell,
|
||||
LucideBook as Book,
|
||||
LucideBoxes as Boxes,
|
||||
LucideBuilding2 as Building2,
|
||||
LucideCalendar as Calendar,
|
||||
LucideCheck as Check,
|
||||
LucideCheckCircle2 as CheckCircle2,
|
||||
LucideChevronDown as ChevronDown,
|
||||
LucideChevronLeft as ChevronLeft,
|
||||
LucideChevronRight as ChevronRight,
|
||||
LucideChevronUp as ChevronUp,
|
||||
LucideCircle as Circle,
|
||||
LucideClock as Clock,
|
||||
LucideCode2 as Code2,
|
||||
LucideCompass as Compass,
|
||||
LucideCopy as Copy,
|
||||
LucideCreditCard as CreditCard,
|
||||
LucideDatabase as Database,
|
||||
LucideDownload as Download,
|
||||
LucideFilter as Filter,
|
||||
LucideFlag as Flag,
|
||||
LucideFolder as Folder,
|
||||
LucideGlobe as Globe,
|
||||
LucideHeart as Heart,
|
||||
LucideHelpCircle as HelpCircle,
|
||||
LucideHistory as History,
|
||||
LucideHome as Home,
|
||||
LucideImage as Image,
|
||||
LucideImages as Images,
|
||||
LucideInfo as Info,
|
||||
LucideLayoutGrid as LayoutGrid,
|
||||
LucideLineChart as LineChart,
|
||||
LucideLink as Link,
|
||||
LucideList as List,
|
||||
LucideLoader2 as Loader2,
|
||||
LucideLock as Lock,
|
||||
LucideLogOut as LogOut,
|
||||
LucideMegaphone as Megaphone,
|
||||
LucideMenu as Menu,
|
||||
LucideMinus as Minus,
|
||||
LucideMonitor as Monitor,
|
||||
LucideNetwork as Network,
|
||||
LucidePackage as Package,
|
||||
LucidePalette as Palette,
|
||||
LucidePencil as Pencil,
|
||||
LucidePlus as Plus,
|
||||
LucidePlusCircle as PlusCircle,
|
||||
LucideSave as Save,
|
||||
LucideScale as Scale,
|
||||
LucideSearch as Search,
|
||||
LucideSettings as Settings,
|
||||
LucideShield as Shield,
|
||||
LucideShoppingCart as ShoppingCart,
|
||||
LucideSlidersHorizontal as SlidersHorizontal,
|
||||
LucideSquare as Square,
|
||||
LucideStar as Star,
|
||||
LucideStore as Store,
|
||||
LucideTable as Table,
|
||||
LucideTag as Tag,
|
||||
LucideTags as Tags,
|
||||
LucideTrash2 as Trash2,
|
||||
LucideTriangleAlert as TriangleAlert,
|
||||
LucideUpload as Upload,
|
||||
LucideUser as User,
|
||||
LucideUsers as Users,
|
||||
LucideVideo as Video,
|
||||
LucideX as X,
|
||||
LucideXCircle as XCircle
|
||||
} from '@lucide/angular';
|
||||
|
||||
/**
|
||||
* Canonical name -> Lucide icon map for the whole app (storefront + builder + backoffice).
|
||||
* One entry per concept so every screen renders the same icon for the same meaning
|
||||
* (RC UI Sprint - Icon & Visual Language Audit). Extend this list rather than
|
||||
* importing Lucide icons ad hoc in individual components.
|
||||
*/
|
||||
export const APP_ICONS = {
|
||||
home: Home,
|
||||
store: Store,
|
||||
cart: ShoppingCart,
|
||||
package: Package,
|
||||
boxes: Boxes,
|
||||
folder: Folder,
|
||||
tag: Tag,
|
||||
tags: Tags,
|
||||
users: Users,
|
||||
user: User,
|
||||
settings: Settings,
|
||||
chartBar: BarChart3,
|
||||
chartLine: LineChart,
|
||||
search: Search,
|
||||
filter: Filter,
|
||||
heart: Heart,
|
||||
scale: Scale,
|
||||
bell: Bell,
|
||||
image: Image,
|
||||
images: Images,
|
||||
palette: Palette,
|
||||
monitor: Monitor,
|
||||
shield: Shield,
|
||||
lock: Lock,
|
||||
database: Database,
|
||||
upload: Upload,
|
||||
download: Download,
|
||||
edit: Pencil,
|
||||
trash: Trash2,
|
||||
copy: Copy,
|
||||
plus: Plus,
|
||||
plusCircle: PlusCircle,
|
||||
minus: Minus,
|
||||
check: Check,
|
||||
checkCircle: CheckCircle2,
|
||||
x: X,
|
||||
xCircle: XCircle,
|
||||
arrowUp: ArrowUp,
|
||||
arrowDown: ArrowDown,
|
||||
arrowLeft: ArrowLeft,
|
||||
arrowRight: ArrowRight,
|
||||
chevronUp: ChevronUp,
|
||||
chevronDown: ChevronDown,
|
||||
chevronLeft: ChevronLeft,
|
||||
chevronRight: ChevronRight,
|
||||
info: Info,
|
||||
help: HelpCircle,
|
||||
warning: TriangleAlert,
|
||||
clock: Clock,
|
||||
calendar: Calendar,
|
||||
menu: Menu,
|
||||
alignLeft: AlignLeft,
|
||||
book: Book,
|
||||
building: Building2,
|
||||
code: Code2,
|
||||
compass: Compass,
|
||||
creditCard: CreditCard,
|
||||
flag: Flag,
|
||||
globe: Globe,
|
||||
history: History,
|
||||
link: Link,
|
||||
list: List,
|
||||
megaphone: Megaphone,
|
||||
logOut: LogOut,
|
||||
network: Network,
|
||||
slidersHorizontal: SlidersHorizontal,
|
||||
spinner: Loader2,
|
||||
star: Star,
|
||||
stop: Square,
|
||||
table: Table,
|
||||
layoutGrid: LayoutGrid,
|
||||
verified: BadgeCheck,
|
||||
video: Video,
|
||||
circle: Circle
|
||||
} as const;
|
||||
|
||||
export type AppIconName = keyof typeof APP_ICONS;
|
||||
39
src/app/shared/ui/icon/icon.component.ts
Normal file
39
src/app/shared/ui/icon/icon.component.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
||||
import { LucideDynamicIcon } from '@lucide/angular';
|
||||
import { APP_ICONS, type AppIconName } from './icon-registry';
|
||||
|
||||
/**
|
||||
* Single entry point for every icon in the app. Renders a Lucide icon by
|
||||
* canonical name (see icon-registry.ts) so every screen uses one icon family
|
||||
* at one consistent size/stroke-width by default.
|
||||
*
|
||||
* Decorative by default (aria-hidden). Pass `ariaLabel` only when the icon
|
||||
* itself carries meaning with no adjacent text (e.g. inside an icon-only
|
||||
* button) - the label belongs on the interactive element when there is one.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-icon',
|
||||
standalone: true,
|
||||
imports: [LucideDynamicIcon],
|
||||
template: `
|
||||
<svg
|
||||
[lucideIcon]="iconData()"
|
||||
[size]="size()"
|
||||
[strokeWidth]="strokeWidth()"
|
||||
[title]="ariaLabel()"
|
||||
></svg>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: {
|
||||
class: 'app-icon',
|
||||
'[style.display]': "'inline-flex'"
|
||||
}
|
||||
})
|
||||
export class IconComponent {
|
||||
readonly name = input.required<AppIconName>();
|
||||
readonly size = input<number>(20);
|
||||
readonly strokeWidth = input<number>(2);
|
||||
readonly ariaLabel = input<string | null>(null);
|
||||
|
||||
protected readonly iconData = computed(() => APP_ICONS[this.name()]);
|
||||
}
|
||||
Reference in New Issue
Block a user