Icon System

SlexKit includes a built-in icon system powered by Phosphor Icons with a custom registration API for extended icon sets.

Resolution chain

When a component requests an icon by name, the system resolves it through this chain:

  1. Registered icons — custom icons registered via registerIcon() or registerIcons()
  2. Phosphor Icons — 24 bundled Phosphor icons available synchronously
  3. Iconify fallbackloadIcon() fetches from the Iconify API if neither source has the icon

Public API

Registration

registerIcon(name, svg, options?)

Register a single SVG icon globally. All components with an icon field can reference it by name.

function registerIcon(name: string, svg: string, options?: RegisterIconOptions): void;
type RegisterIconOptions = {
  aliases?: string[];    // Alternative names for the same icon
  weight?: IconWeight;   // "regular" | "duotone" — defaults to "regular"
};

Example:

import { registerIcon } from "slexkit";

registerIcon(
  "my-custom-icon",
  `<svg viewBox="0 0 24 24" fill="none" ...>...</svg>`,
  { aliases: ["custom", "my-icon"] }
);

registerIcons(icons, options?)

Register multiple icons at once.

function registerIcons(icons: Record<string, string>, options?: RegisterIconOptions): void;

Example:

import { registerIcons } from "slexkit";

registerIcons(
  {
    "cpu": `<svg>...</svg>`,
    "memory": `<svg>...</svg>`,
    "database": `<svg>...</svg>`,
  },
  { weight: "regular" }
);

clearRegisteredIcons()

Remove all custom registered icons from the global registry.

function clearRegisteredIcons(): void;

Retrieval

getIcon(name, state?)

Resolve an icon synchronously. Returns the SVG string or an empty string if not found.

function getIcon(name: string, state?: IconWeight | IconState): string;

Looks up registered icons first, then falls back to bundled Phosphor icons. Does not fetch from Iconify.

getRegisteredIcon(name, state?)

Look up only from the registered icon registry. Returns the SVG string or an empty string. Does not check Phosphor or Iconify.

function getRegisteredIcon(name: string, state?: IconWeight | IconState): string;

Useful for checking if a custom icon exists without triggering Phosphor or Iconify lookups.

loadIcon(name, state?)

Resolve an icon asynchronously. Returns a Promise that resolves to the SVG string.

function loadIcon(name: string, state?: IconWeight | IconState): Promise<string>;

Searches registered icons → Phosphor → fetches from Iconify API as a last resort. Use this when the icon set is not known at build time.

Name and weight utilities

normalizeIconName(name)

Normalize an icon name to standard kebab-case format. Handles set prefixes.

function normalizeIconName(name: string): string;

Examples:

Set prefixes are normalized: "phosphor" / "phosphor-icons" become "ph".

resolveIconWeight(state?)

Resolve the icon weight from component state. Auto-selects "duotone" for selected/active/pressed/current states.

function resolveIconWeight(state?: IconWeight | IconState): IconWeight;
type IconWeight = "regular" | "duotone";
type IconState = {
  selected?: boolean;
  active?: boolean;
  pressed?: boolean;
  current?: boolean;
};

resolveIconifyIcon(name, state?)

Resolve to an Iconify-compatible { prefix, name } pair.

function resolveIconifyIcon(name: string, state?: IconWeight | IconState): { prefix: string; name: string };

iconifySvgUrl(name, state?)

Build the full Iconify API SVG URL for fetching a remote icon.

function iconifySvgUrl(name: string, state?: IconWeight | IconState): string;

iconCacheKey(name, state?)

Return the lookup key used internally for icon caching.

function iconCacheKey(name: string, state?: IconWeight | IconState): string;

Built-in Phosphor icons

SlexKit bundles 23 Phosphor Icons in both regular and duotone weights (46 total SVG files):

Icon Name
CaretDown caret-down
Check check
CircleHalf circle-half
List list
Moon moon
Sun sun
Code code
BookOpenText book-open-text
CursorClick cursor-click
GearSix gear-six
Nut nut
Screwdriver screwdriver
Sparkle sparkle
TerminalWindow terminal-window
Wrench wrench
Copy copy
Eye eye
ArrowSquareOut arrow-square-out
SplitHorizontal split-horizontal
SquareHalf square-half
SquareSplitHorizontal square-split-horizontal
File file
X x

Icon naming convention

Icons are referenced in Slex expressions using kebab-case names:

"button:add": { text: "Add", icon: "plus" }
"link:docs": { text: "Docs", icon: "book-open-text" }

To use a custom icon set prefix:

"card:info": { title: "Info", icon: "ph:info" }
"callout:tip": { title: "Tip", icon: "my-set:custom-bulb" }

The name resolution chain handles: custom-icon → registered first → bundled Phosphor → Iconify fetch (async only).

Iconify fallback

When loadIcon() cannot find an icon in the registered or Phosphor sets, it fetches from the Iconify API:

https://api.iconify.design/<prefix>/<name>.svg

This enables access to thousands of icons beyond the built-in set. Fetched SVGs are sanitized before use.

Usage in components

Components that accept an icon prop:

Component Icon location
Button Before text
Badge Before text
Card Title area
Callout Title area
Section Eyebrow/title area
Link Before text
Divider Before/around label
Tabs Tab header (icon or iconOnly mode)
Toast Title area
Stat Next to value
Accordion Trigger area
Collapsible Trigger area
Submit Button icon area

Icons automatically use duotone weight when the component or icon is in a selected/active/pressed state.