Use the component directly. Named icons resolve against a pinned Lucide set by default via provideKikitaUi(); register your own set with provideKuiIcons(), host the Lucide files yourself, or opt out entirely.

import { KuiIcon } from '@kikita-labs/ui';

Use labels only when the icon carries meaning; omit labels for decorative support icons. Size with named presets or CSS lengths.

Package verified
<div class="basic-icon-example">
  <span class="basic-icon-example__status">
    <kui-icon [source]="checkIcon" label="Success" size="18px" />
    Package verified
  </span>

  <button kuiIconButton type="button" shape="soft" aria-label="Run magic action">
    <kui-icon [source]="sparkIcon" />
  </button>
</div>

An icon is either glyph data (drawn from an allowlist of elements and attributes, safe from any source, rendered synchronously, also on the server) or trusted SVG markup. strokeWidth and absoluteStrokeWidth restyle stroke-based icons.

<div class="icon-glyph-example">
  <kui-icon [source]="gauge" label="Gauge" size="32px" />
  <kui-icon [source]="gauge" label="Gauge, thin stroke" size="32px" [strokeWidth]="1" />
  <kui-icon [source]="gauge" label="Gauge, heavy stroke" size="32px" [strokeWidth]="3" />
  <kui-icon [source]="gauge" label="Large gauge, constant stroke" size="64px" absoluteStrokeWidth />
</div>
  • A glyph is { node, viewBox? }, where node lists drawing elements in paint order in the icon-node layout of Lucide; only path, line, polyline, polygon, circle, ellipse and rect are drawn, and an unknown element invalidates the glyph.
  • strokeWidth sets --kui-icon-stroke-width in glyph-grid units (24 by 24 for Lucide) and absoluteStrokeWidth keeps the stroke the same number of pixels at any size (--kui-icon-vector-effect: non-scaling-stroke). Both are plain CSS custom properties, so they also work on :root or a subtree. Filled shapes and markup with an inline stroke-width style are not affected.

Register an icon set for the application or a route with provideKuiIcons() (it returns environment providers), or scope one to a component subtree by providing the KUI_ICONS multi token in that component's providers. Later registrations win for names they both define.

Lucide (default)
Material Symbols
Custom set
<div class="swap-icon-set-example">
  <div class="swap-icon-set-example__item">
    <kui-icon name="star" label="Lucide star" size="28px" />
    <span>Lucide (default)</span>
  </div>

  <div class="swap-icon-set-example__item">
    <app-material-icon-scope />
    <span>Material Symbols</span>
  </div>

  <div class="swap-icon-set-example__item">
    <app-custom-icon-scope />
    <span>Custom set</span>
  </div>
</div>

Glyph data is safe from any source; trusted SVG markup is a trusted-code API, not a user-content API.

  • The default Lucide set is read at a pinned lucide-static version (KUI_LUCIDE_STATIC_VERSION, 1.51.0), so a library release always draws the same icons. The fetched file is converted to glyph data with the allowlist instead of being inserted as HTML: a replaced or compromised file cannot inject script or load another resource, and a file with anything else (script, use, text) is rejected and the icon stays empty. Names that are not Lucide kebab-case names resolve to nothing without a request.
  • Allow connect-src https://cdn.jsdelivr.net in a Content Security Policy, host the files yourself with createKuiLucideResolver({ baseUrl }), or set provideKikitaUi({ icons: false }) to make no request at all. Names resolved through the default set need a request, so they render when it settles; a name found in a static registry renders on the first pass.
  • Register SVG strings from static application code only and pass only trusted static SVG to [source]; return glyph data from a custom resolver so a response cannot carry markup, and never resolve a name to a URL built from user input.
  • Use src for normal image URLs when you do not need inline SVG styling.

Inputs, icon content types and provider API verified against @kikita-labs/ui v2.0.0 public typings.

NameTypeDefaultDescription
kui-iconComponent-Renders an icon from a registered name, trusted inline SVG source, or image URL.
nameKuiIconName | undefinedundefinedIcon name resolved from icons registered with provideKuiIcons(), falling back to the default pinned Lucide resolver unless disabled. A name in a static registry renders on the first pass; others render when the async resolver settles.
sourceKuiIconContent | undefinedundefinedDirect icon content: KuiIconGlyph data (safe from any source) or trusted static inline SVG markup. It takes precedence over name and renders synchronously.
srcstring | undefinedundefinedExternal image URL used when no source or registered name is provided.
labelstring | undefinedundefinedAccessible name for meaningful icons. Omit it for decorative icons.
size'2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | string | number'1em'Named presets map to Kikita icon-size tokens. Numeric values become pixels, and arbitrary CSS size strings pass through.
provideKuiIcons(icons)EnvironmentProviders-Registers a static map of trusted SVG strings, or an async KuiIconResolver function, for name-based icon lookup. Later registrations take precedence for names both define. Route-level only; component providers cannot accept EnvironmentProviders.
KUI_ICONSInjectionToken<readonly KuiIconRegistry[]>-The multi-provider token behind provideKuiIcons(). Provide it directly in a component's own providers ({ provide: KUI_ICONS, multi: true, useValue }) to scope an icon-set override to that subtree.
provideKikitaUi({ icons })'lucide' | false'lucide'Registers kui-icon's default resolvers: Lucide (lazily fetched SVG markup from the jsDelivr CDN) and the built-in KUI_BRAND_ICONS set (currently just the 'kikita-brand' wordmark, resolved locally). Set to false to opt out of both.
strokeWidthnumber | string | undefinedundefinedStroke width in glyph-grid units (24 by 24 for Lucide). Sets --kui-icon-stroke-width on the host; unset keeps the icon weight or the token of an ancestor.
absoluteStrokeWidthbooleanfalseKeeps the stroke the same number of pixels at any icon size. Sets --kui-icon-vector-effect: non-scaling-stroke on the host.
KuiIconGlyph / KuiIconContenttypes-Glyph data { node, viewBox? } drawn through an allowlist, and the union of glyph data and trusted SVG markup accepted by source and by registries.
createKuiLucideResolver(options?)(options?: KuiLucideResolverOptions) => KuiIconResolver-The safe Lucide resolver for another lucide-static version or for files you host (baseUrl, no trailing slash). Fetched text is converted to glyph data, never inserted as markup.
KUI_LUCIDE_STATIC_VERSIONstring'1.51.0'The exact lucide-static version of the default resolver. It changes only with a library release.
--kui-icon-stroke-width / --kui-icon-vector-effectCSS custom properties-Set by strokeWidth and absoluteStrokeWidth; set them on :root or a subtree to restyle every stroke-based icon, structural icons included.

Icon accessibility depends on whether the graphic adds information.

  • Omit label for decorative icons so they are hidden from assistive technology.
  • Provide label when the icon itself communicates status, action, or identity.
  • Prefer visible text next to icons for actions; icon-only buttons need an accessible name.
  • Keep icon sizing proportional to surrounding text or control height.

Consumer-visible changes of @kikita-labs/ui 2.0 for icons.

  • The class is KuiIcon (it was KuiIconComponent); ng update @kikita-labs/ui renames the import.
  • The default Lucide set moved from the floating lucide-static@1 to a pinned version, is converted to glyph data and may need connect-src in your CSP. KuiIconSource stays the markup string type; registries and resolvers may also return KuiIconGlyph data.
  • provideKuiIcons() returns environment providers: put it in the application config, a route or an environment injector. A static registry answers on the first pass without a promise, and names are matched against the registry's own keys only, so name="constructor" no longer returns a function.
  • New inputs strokeWidth and absoluteStrokeWidth, and a kui.components layer stylesheet: kui-icon needs kikita-ui.css like every other component.