Icon
Render icons from a name, glyph data, trusted SVG markup or an image URL, with accessible decorative and meaningful states. The icons components draw for themselves are a separate, structural system.
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.
<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? }, wherenodelists drawing elements in paint order in the icon-node layout of Lucide; onlypath,line,polyline,polygon,circle,ellipseandrectare drawn, and an unknown element invalidates the glyph. strokeWidthsets--kui-icon-stroke-widthin glyph-grid units (24 by 24 for Lucide) andabsoluteStrokeWidthkeeps 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:rootor a subtree. Filled shapes and markup with an inlinestroke-widthstyle 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.
<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-staticversion (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.netin a Content Security Policy, host the files yourself withcreateKuiLucideResolver({ baseUrl }), or setprovideKikitaUi({ 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
srcfor 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.
| Name | Type | Default | Description |
|---|---|---|---|
| kui-icon | Component | - | Renders an icon from a registered name, trusted inline SVG source, or image URL. |
| name | KuiIconName | undefined | undefined | Icon 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. |
| source | KuiIconContent | undefined | undefined | Direct icon content: KuiIconGlyph data (safe from any source) or trusted static inline SVG markup. It takes precedence over name and renders synchronously. |
| src | string | undefined | undefined | External image URL used when no source or registered name is provided. |
| label | string | undefined | undefined | Accessible 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_ICONS | InjectionToken<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. |
| strokeWidth | number | string | undefined | undefined | Stroke 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. |
| absoluteStrokeWidth | boolean | false | Keeps the stroke the same number of pixels at any icon size. Sets --kui-icon-vector-effect: non-scaling-stroke on the host. |
| KuiIconGlyph / KuiIconContent | types | - | 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_VERSION | string | '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-effect | CSS 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
labelfor decorative icons so they are hidden from assistive technology. - Provide
labelwhen 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 wasKuiIconComponent);ng update @kikita-labs/uirenames the import. - The default Lucide set moved from the floating
lucide-static@1to a pinned version, is converted to glyph data and may needconnect-srcin your CSP.KuiIconSourcestays the markup string type; registries and resolvers may also returnKuiIconGlyphdata. 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, soname="constructor"no longer returns a function.- New inputs
strokeWidthandabsoluteStrokeWidth, and akui.componentslayer stylesheet:kui-iconneedskikita-ui.csslike every other component.