# Icon Item

- Entry point: `@koobiq/components/icon`
- NgModule: `KbqIconModule`
- Page: https://koobiq.io/en/components/icon-item/overview

## Overview

A backing icon can be used instead of an illustration where you want to attract attention with graphics.

**Example: Icon-item** (`icon-item-overview`)

```ts icon-item-overview-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqComponentColors } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';

@Component({
    selector: 'icon-item-overview-example',
    imports: [
        KbqIconModule
    ],
    template: `
        <div class="example-icon-item-container layout-column">
            <i kbq-icon-item="kbq-bell_16" [color]="colors.Theme"></i>
        </div>
    `,
    styleUrls: ['icon-item-overview-example.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class IconItemOverviewExample {
    colors = KbqComponentColors;
}
```

```css icon-item-overview-example.css
.example-icon-item-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
```

### Color

**Example: Icon-item color** (`icon-item-color`)

```ts icon-item-color-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqComponentColors } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';

@Component({
    selector: 'icon-item-color-example',
    imports: [
        KbqIconModule
    ],
    template: `
        <div class="example-icon-item-layout layout-row">
            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Theme"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Theme</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Contrast"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Contrast</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Success"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Success</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Warning"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Warning</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Error"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Error</div>
            </div>
        </div>
    `,
    styleUrls: ['icon-item-color-example.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class IconItemColorExample {
    colors = KbqComponentColors;
}
```

```css icon-item-color-example.css
.example-icon-item-layout {
    width: 100%;
    height: 100%;
    min-height: 100%;

    display: flex;
    justify-content: space-around;
    align-items: center;
}

.example-icon-item-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.example-icon-item-container__name {
    padding-top: 8px;
}
```

### Variant

**Example: Icon Item Variant** (`icon-item-variant`)

```ts icon-item-variant-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqComponentColors } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';

@Component({
    selector: 'icon-item-variant-example',
    imports: [
        KbqIconModule
    ],
    template: `
        <div class="example-icon-item-layout layout-row">
            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Theme"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Solid</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Theme" [fade]="true"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Fade</div>
            </div>
        </div>
    `,
    styleUrls: ['icon-item-variant-example.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class IconItemVariantExample {
    colors = KbqComponentColors;
}
```

```css icon-item-variant-example.css
.example-icon-item-layout {
    width: 100%;
    height: 100%;
    min-height: 100%;

    display: flex;
    justify-content: space-around;
    align-items: center;
}

.example-icon-item-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.example-icon-item-container__name {
    padding-top: 8px;
}
```

### Size

**Example: Icon-item size** (`icon-item-size`)

```ts icon-item-size-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqComponentColors } from '@koobiq/components/core';
import { KbqIconModule } from '@koobiq/components/icon';

@Component({
    selector: 'icon-item-size-example',
    imports: [
        KbqIconModule
    ],
    template: `
        <div class="example-icon-item-layout layout-row">
            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [big]="true" [color]="colors.Theme"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Big</div>
            </div>

            <div class="example-icon-item-container">
                <i kbq-icon-item="kbq-bell_16" [color]="colors.Theme"></i>
                <div class="example-icon-item-container__name kbq-text-normal">Normal</div>
            </div>
        </div>
    `,
    styleUrls: ['icon-item-size-example.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class IconItemSizeExample {
    colors = KbqComponentColors;
}
```

```css icon-item-size-example.css
.example-icon-item-layout {
    width: 100%;
    height: 100%;
    min-height: 100%;

    display: flex;
    justify-content: space-around;
    align-items: center;
}

.example-icon-item-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.example-icon-item-container__name {
    padding-top: 8px;
}
```

## API

### Components

#### KbqIcon (component)

Renders an icon on the element it is applied to: a `@koobiq/icons` font glyph by default, or an inline
`<svg>` when the name resolves through a configured `KbqIconRegistry`. A name that does not resolve
falls back to the font class, and every later name is resolved again.

The host is `aria-hidden` by default: an icon carries no text of its own, and in nearly every place the
library and its consumers use one it repeats a label that is already there. A meaningful icon opts out
with `aria-hidden="false"`, and then has to supply its own `role="img"` and `aria-label`.

```ts
@Component({ selector: '[kbq-icon]' })
class KbqIcon extends KbqColorDirective {
    readonly ariaHidden = input<boolean | undefined>(undefined, {
        alias: 'aria-hidden'
    });
    readonly iconSize = input<number | undefined>();
    autoColor = input<boolean | undefined>();
    readonly color = input<T | null | undefined>();
    hasError: boolean;
    iconName: string | undefined;
    get colorClassName(): string;
    getHostElement(): HTMLElement;
    setDefaultColor(color: T): void;
}
```

- `[aria-hidden]`: `boolean | undefined` — Whether the icon is hidden from assistive technology. Left unbound, it falls back to
  `defaultAriaHidden`, which is `true` for a decorative icon and `false` for an interactive one.
- `[iconSize]`: `number | undefined` — Rendered size of the icon in pixels. Left unset, the size is read from the `_<px>` suffix of the
  icon name (`kbq-plus_16` → 16), which is the `@koobiq/icons` convention; a name without one is
  rendered at whatever size the surrounding styles give it.
- `[autoColor]`: `boolean | undefined` — Whether the icon follows the error state of the host it sits in (a form field, for one), painting
  itself red while that host reports an error.
- `[color]`: `T | null | undefined` — Color of the component. A value set in code holds until the input changes, and the default color is used
  while both are unset or falsy.
- `hasError`: `boolean` — Whether the icon takes the error color whatever its `color` is. Set by a host that tints the icons
  it holds, such as `KbqEmptyState`.
- `iconName`: `string | undefined` — Name of an icon within a `@koobiq/icons`. Accepts "namespace:name" syntax.
- `colorClassName`: `string` — current class name of color
- `setDefaultColor()`: `void` — this color will be used as a default value. For example [color]="'' | false | undefined | null".

#### KbqIconButton (component)

An icon that acts as a button. Applied to a native `<button>` it only adds the styling; applied to any
other element — `<i>` is what the library itself mostly uses — it also supplies the semantics the
element does not have: `role="button"` and `aria-disabled`. It does not synthesize Enter/Space
activation itself — attach a `(keydown.enter)`/`(keydown.space)` listener where it is used.

It has no text of its own, so give it an `aria-label` (or an `aria-labelledby`); in dev mode it warns
when it has neither.

It extends `KbqIcon` for the rendering, but deliberately does not register under that DI token: a
`contentChild(KbqIcon)` is looking for a decorative icon to position or tint, and an interactive
control is not one. See the note on `KbqIconItem`.

```ts
@Component({ selector: '[kbq-icon-button]' })
class KbqIconButton extends KbqIcon {
    readonly size = input<KbqIconButtonSize>('normal');
    tabindex = input<number | null | undefined>();
    disabled = input<boolean | undefined>();
    readonly ariaHidden = input<boolean | undefined>(undefined, {
        alias: 'aria-hidden'
    });
    readonly iconSize = input<number | undefined>();
    autoColor = input<boolean | undefined>();
    readonly color = input<T | null | undefined>();
    hasError: boolean;
    iconName: string | undefined;
    get colorClassName(): string;
    getHostElement(): HTMLElement;
    setDefaultColor(color: T): void;
}
```

- `[size]`: `KbqIconButtonSize` — Size of the icon button.
- `[tabindex]`: `number | null | undefined` — Position of the button in the tab order. A disabled button is taken out of it entirely.
- `[disabled]`: `boolean | undefined` — Whether the button is disabled.
- `[aria-hidden]`: `boolean | undefined` — Whether the icon is hidden from assistive technology. Left unbound, it falls back to
  `defaultAriaHidden`, which is `true` for a decorative icon and `false` for an interactive one.
- `[iconSize]`: `number | undefined` — Rendered size of the icon in pixels. Left unset, the size is read from the `_<px>` suffix of the
  icon name (`kbq-plus_16` → 16), which is the `@koobiq/icons` convention; a name without one is
  rendered at whatever size the surrounding styles give it.
- `[autoColor]`: `boolean | undefined` — Whether the icon follows the error state of the host it sits in (a form field, for one), painting
  itself red while that host reports an error.
- `[color]`: `T | null | undefined` — Color of the component. A value set in code holds until the input changes, and the default color is used
  while both are unset or falsy.
- `hasError`: `boolean` — Whether the icon takes the error color whatever its `color` is. Set by a host that tints the icons
  it holds, such as `KbqEmptyState`.
- `iconName`: `string | undefined` — Name of an icon within a `@koobiq/icons`. Accepts "namespace:name" syntax.
- `colorClassName`: `string` — current class name of color
- `setDefaultColor()`: `void` — this color will be used as a default value. For example [color]="'' | false | undefined | null".

#### KbqIconItem (component)

An icon on a filled round background — the status badge of an alert or an empty state. Decorative like
`KbqIcon`, and hidden from assistive technology by the same default.

Host metadata is inherited from `KbqIcon` through `ɵɵInheritDefinitionFeature`; DI tokens are not, so a
`contentChild(KbqIcon)` does not match an icon item. That is deliberate — a host that wants both asks
for both, the way `KbqAlert` does, and telling them apart is what lets it report two projected icons.

```ts
@Component({ selector: '[kbq-icon-item]' })
class KbqIconItem extends KbqIcon {
    readonly fade = input<boolean>(false);
    readonly big = input<boolean>(false);
    readonly ariaHidden = input<boolean | undefined>(undefined, {
        alias: 'aria-hidden'
    });
    readonly iconSize = input<number | undefined>();
    autoColor = input<boolean | undefined>();
    readonly color = input<T | null | undefined>();
    hasError: boolean;
    iconName: string | undefined;
    get colorClassName(): string;
    getHostElement(): HTMLElement;
    setDefaultColor(color: T): void;
}
```

- `[fade]`: `boolean` — Whether the background is the translucent "fade" variant of the color rather than the solid one.
- `[big]`: `boolean` — Whether the item is rendered at the larger of its two sizes.
- `[aria-hidden]`: `boolean | undefined` — Whether the icon is hidden from assistive technology. Left unbound, it falls back to
  `defaultAriaHidden`, which is `true` for a decorative icon and `false` for an interactive one.
- `[iconSize]`: `number | undefined` — Rendered size of the icon in pixels. Left unset, the size is read from the `_<px>` suffix of the
  icon name (`kbq-plus_16` → 16), which is the `@koobiq/icons` convention; a name without one is
  rendered at whatever size the surrounding styles give it.
- `[autoColor]`: `boolean | undefined` — Whether the icon follows the error state of the host it sits in (a form field, for one), painting
  itself red while that host reports an error.
- `[color]`: `T | null | undefined` — Color of the component. A value set in code holds until the input changes, and the default color is used
  while both are unset or falsy.
- `hasError`: `boolean` — Whether the icon takes the error color whatever its `color` is. Set by a host that tints the icons
  it holds, such as `KbqEmptyState`.
- `iconName`: `string | undefined` — Name of an icon within a `@koobiq/icons`. Accepts "namespace:name" syntax.
- `colorClassName`: `string` — current class name of color
- `setDefaultColor()`: `void` — this color will be used as a default value. For example [color]="'' | false | undefined | null".

### Services

#### KbqIconRegistry (service)

```ts
@Injectable({ providedIn: 'root' })
class KbqIconRegistry {
    addSvgIcon(
        name: string,
        url: SafeResourceUrl,
        options?: KbqIconOptions
    ): void;
    addSvgIconLiteral(
        name: string,
        literal: SafeHtml,
        options?: KbqIconOptions
    ): void;
    addSvgIconInNamespace(
        namespace: string,
        name: string,
        url: SafeResourceUrl,
        options?: KbqIconOptions
    ): void;
    addSvgIconLiteralInNamespace(
        namespace: string,
        name: string,
        literal: SafeHtml,
        options?: KbqIconOptions
    ): void;
    addSvgIconSet(url: SafeResourceUrl, options?: KbqIconOptions): void;
    addSvgIconSetInNamespace(
        namespace: string,
        url: SafeResourceUrl,
        options?: KbqIconOptions
    ): void;
    getNamedSvgIcon(
        name: string,
        namespace?: string
    ): Observable<SVGElement>;
}
```

- `addSvgIcon()`: `void` — Registers an SVG icon by URL in the default namespace.
- `addSvgIconLiteral()`: `void` — Registers an SVG icon from an inline HTML string in the default namespace.
- `addSvgIconInNamespace()`: `void` — Registers an SVG icon by URL under the given namespace.
- `addSvgIconLiteralInNamespace()`: `void` — Registers an SVG icon from an inline HTML string under the given namespace.
- `addSvgIconSet()`: `void` — Registers an SVG sprite file in the default namespace. Icons are looked up by their `symbol id`.
- `addSvgIconSetInNamespace()`: `void` — Registers an SVG sprite file under the given namespace. Duplicate URLs are silently ignored.
- `getNamedSvgIcon()`: `Observable<SVGElement>` — Emits a cloned SVGElement for the given name.
  Accepts "namespace:name" syntax.

### Functions

#### kbqIconsDictProvider (function)

Registers a name→URL dictionary as an icon resolver. Values are fetched at runtime through `HttpClient`.

A value starting with `<` is taken as inline markup and passed through Angular's HTML sanitizer,
which drops `<svg>` wholesale — register inline icons with
`KbqIconRegistry.addSvgIconLiteral(name, sanitizer.bypassSecurityTrustHtml(svg))` instead, where the
markup is a `SafeHtml` the application has explicitly vouched for.

```ts
kbqIconsDictProvider({ 'chevron-down-s_16': '/assets/icons/chevron-down-s_16.svg' })
```

```ts
function kbqIconsDictProvider(dict: Record<string, string>): Provider;
```

#### kbqIconsProvider (function)

Configures the icon registry to load icons from one or more SVG sprite assets.

```ts
function kbqIconsProvider(...sprites: KbqIconsConfig[]): Provider;
```

#### kbqIconsResolverProvider (function)

Registers a resolver function that maps icon names to SVG strings or URLs.
Multiple resolvers can be registered; they are tried in registration order.

```ts
function kbqIconsResolverProvider(resolver: KbqIconResolver): Provider;
```

### Types

#### KbqIconButtonSize (type)

Size options for `KbqIconButton`.
- `compact`: 16px icon with padding, 24×24px container.
- `normal`: 24px icon, no padding.

```ts
type KbqIconButtonSize = 'compact' | 'normal';
```

#### KbqIconOptions (interface)

```ts
interface KbqIconOptions {
    viewBox?: string;
    withCredentials?: boolean;
}
```

#### KbqIconResolver (type)

A function that resolves an icon name to either an inline SVG string or a URL string.
Return `null` to indicate this resolver does not handle the given name.

```ts
type KbqIconResolver = (name: string) => string | null;
```

#### KbqIconsConfig (interface)

```ts
interface KbqIconsConfig {
    spriteUrl: string;
    namespace?: string;
}
```

- `spriteUrl`: `string` — URL to the SVG sprite file. Must be served as a static asset.
- `namespace?`: `string` — Optional namespace to register the sprite under.

### Constants

#### KBQ_ICON_RESOLVER (const)

Multi-valued injection token for icon resolver functions.
Resolvers are tried in registration order; the first non-null result wins.

```ts
const KBQ_ICON_RESOLVER: InjectionToken<KbqIconResolver[]>;
```

#### KBQ_ICONS_CONFIG (const)

```ts
const KBQ_ICONS_CONFIG: InjectionToken<KbqIconsConfig[]>;
```
