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/platform-browser": "21.1.5",
|
||||||
"@angular/router": "21.1.5",
|
"@angular/router": "21.1.5",
|
||||||
"@angular/service-worker": "21.1.5",
|
"@angular/service-worker": "21.1.5",
|
||||||
|
"@lucide/angular": "^1.25.0",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primeng": "^21.0.3",
|
"primeng": "^21.0.3",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
@@ -2009,6 +2010,19 @@
|
|||||||
"win32"
|
"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": {
|
"node_modules/@modelcontextprotocol/sdk": {
|
||||||
"version": "1.26.0",
|
"version": "1.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"@angular/platform-browser": "21.1.5",
|
"@angular/platform-browser": "21.1.5",
|
||||||
"@angular/router": "21.1.5",
|
"@angular/router": "21.1.5",
|
||||||
"@angular/service-worker": "21.1.5",
|
"@angular/service-worker": "21.1.5",
|
||||||
|
"@lucide/angular": "^1.25.0",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primeng": "^21.0.3",
|
"primeng": "^21.0.3",
|
||||||
"rxjs": "~7.8.0",
|
"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