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:
sdarbinyan
2026-07-20 01:49:38 +04:00
parent fd5a436220
commit f3c8a8cc96
4 changed files with 216 additions and 0 deletions

View 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()]);
}