Files
marketplaces/src/app/shared/ui/icon/icon.component.ts

42 lines
1.3 KiB
TypeScript
Raw Normal View History

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()"
[color]="color()"
[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 color = input<string>('currentColor');
readonly strokeWidth = input<number>(2);
readonly ariaLabel = input<string | null>(null);
protected readonly iconData = computed(() => APP_ICONS[this.name()]);
}