Icons

@tailng-ui/icons provides a lazy-loading icon system with built-in Lucide support and an extensible pack API for any SVG icon set.

Getting Started

Installation

Install the icons package along with the @ng-icons peer dependencies for Lucide (the default built-in pack).

pnpm

bash
pnpm add @tailng-ui/icons @ng-icons/core @ng-icons/lucide
Configuration

Default Setup — Lucide Icons

Call provideTngIcons() in your application config. With no arguments, Lucide is registered as the default pack — no extra configuration required.

app.config.ts

typescript
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideTngIcons } from '@tailng-ui/icons';

export const appConfig: ApplicationConfig = {
  providers: [
    provideTngIcons(), // uses Lucide by default
  ],
};

Using icons in templates

Import TngIcon into your component and use the <tng-icon> element. Icons are loaded lazily on first use.

my.component.html

html
<!-- decorative icon alongside text (aria-hidden by default) -->
<tng-icon icon="home" class="h-5 w-5" />

<!-- meaningful standalone icon with accessible label -->
<tng-icon icon="search" label="Search" class="h-5 w-5" />

<!-- kebab-case and camelCase icon names are both supported -->
<tng-icon icon="arrow-right" class="h-4 w-4" />
<tng-icon icon="arrowRight" class="h-4 w-4" />

Icon reference syntax

Icon names can be plain (resolved against the default pack) or prefixed with pack-name: to reference a specific pack explicitly. Both kebab-case and camelCase names are supported for Lucide.

pack:name syntax

html
<!-- no prefix → uses the default pack (lucide) -->
<tng-icon icon="star" />

<!-- explicit pack:name syntax -->
<tng-icon icon="lucide:star" />
<tng-icon icon="bootstrap:star-fill" />
<tng-icon icon="flags:us" />
Custom Packs

Using Bootstrap Icons

Register a custom pack to use Bootstrap Icons (or any other @ng-icons set) alongside the built-in Lucide pack.

1 — Install the Bootstrap icon set

pnpm

bash
pnpm add @ng-icons/bootstrap-icons

2 — Register the pack with createTngIconPack

Create a loader for each icon you need. Each loader is a function that returns a Promise<string> containing the SVG markup. Loaders are called lazily — only when the icon is first rendered.

icons.provider.ts

typescript
// icons.provider.ts
import { createTngIconPack, provideTngIcons, type TngIconLoader } from '@tailng-ui/icons';

function createBootstrapLoader(exportName: string): TngIconLoader {
  return async () => {
    const mod = await import('@ng-icons/bootstrap-icons') as Record;
    const svg = mod[exportName];
    if (typeof svg !== 'string') {
      throw new Error(`Bootstrap icon "${exportName}" not found.`);
    }
    return svg;
  };
}

const bootstrapPack = createTngIconPack('bootstrap', {
  'star-fill': createBootstrapLoader('bootstrapStarFill'),
  'bell':      createBootstrapLoader('bootstrapBell'),
  'x-circle':  createBootstrapLoader('bootstrapXCircle'),
  // add more icons as needed
});

export const tngIconProviders = provideTngIcons({
  packs: [bootstrapPack],
});

3 — Use in templates

my.component.html

html
<!-- explicit pack prefix -->
<tng-icon icon="bootstrap:star-fill" class="h-5 w-5" />
<tng-icon icon="bootstrap:bell" class="h-5 w-5" />

<!-- when bootstrap is set as defaultPack, prefix is optional -->
<tng-icon icon="star-fill" class="h-5 w-5" />

Multiple Packs & Default Pack

Register several packs at once and control which one resolves un-prefixed icon names.

Pass an array of packs to packs. The defaultPack option selects which pack resolves icons without a prefix — it must match a registered pack name (built-in or custom).

app.config.ts

typescript
export const tngIconProviders = provideTngIcons({
  defaultPack: 'lucide',          // default pack when no prefix is given
  packs: [bootstrapPack, brandPack],
});
Custom Packs

Other Icon Sources

Custom packs work with any SVG source — inline strings, remote URLs, or your own icon modules.

Inline static SVG

Wrap a hard-coded SVG string in a loader that resolves immediately. Useful for small brand icon sets where tree-shaking is not a concern.

brand-icons.provider.ts

typescript
import { createTngIconPack, provideTngIcons, type TngIconLoader } from '@tailng-ui/icons';

function staticSvg(svg: string): TngIconLoader {
  return () => Promise.resolve(svg);
}

const brandPack = createTngIconPack('brand', {
  logo: staticSvg(
    '',
  ),
  wordmark: staticSvg(
    'MyApp',
  ),
});

export const tngIconProviders = provideTngIcons({ packs: [brandPack] });

Remote SVG via URL

Fetch SVGs from a CDN or API at render time. The icon is cached after the first load, so subsequent renders are instant.

remote-icons.provider.ts

typescript
import { createTngIconPack, provideTngIcons, type TngIconLoader } from '@tailng-ui/icons';

const CDN = 'https://cdn.example.com/icons';

function remoteSvg(path: string): TngIconLoader {
  return async () => {
    const res = await fetch(`${CDN}/${path}.svg`);
    if (!res.ok) throw new Error(`Failed to load icon: ${path}`);
    return res.text();
  };
}

const remoteIconPack = createTngIconPack('remote', {
  avatar: remoteSvg('avatar'),
  dashboard: remoteSvg('dashboard'),
});

export const tngIconProviders = provideTngIcons({ packs: [remoteIconPack] });

Overriding built-in Lucide icons

Set allowBuiltinOverride: true to replace individual icons within a built-in pack name. All other icons in the pack remain untouched.

app.config.ts

typescript
provideTngIcons({
  allowBuiltinOverride: true,
  packs: [
    // Replace individual Lucide icons with your own SVGs
    createTngIconPack('lucide', {
      home: () => Promise.resolve(''),
    }),
  ],
})
API

API Reference

Types and functions exported from @tailng-ui/icons.

provideTngIcons(options?)

Call once in your application config (or in a lazy-loaded route's providers array). Returns Angular EnvironmentProviders.

TngProvideIconsOptions

typescript
interface TngProvideIconsOptions {
  /** Additional icon packs to register alongside the built-in Lucide pack. */
  packs?: TngIconPack[];

  /**
   * Pack used when no prefix is given in an icon ref.
   * Defaults to 'lucide'.
   */
  defaultPack?: string;

  /**
   * Allow a custom pack to shadow a built-in pack name (e.g. 'lucide').
   * Defaults to false.
   */
  allowBuiltinOverride?: boolean;
}

createTngIconPack(name, icons)

Creates a named icon pack from a map of icon names to TngIconLoader functions.

createTngIconPack

typescript
function createTngIconPack(
  name: string,
  icons: Record,
): TngIconPack;

// TngIconLoader: a function that returns the SVG markup as a string
type TngIconLoader = () => Promise;

<tng-icon> component

A standalone Angular component that resolves and renders icon SVGs. Decorative by default — add a label for standalone icons that convey meaning.

TngIcon inputs

typescript
//  component inputs
icon: string;          // required — icon name or "pack:name" ref
label?: string | null; // accessible label; omit for decorative icons