@absoluteui/icons
Icon registry and the built-in icon set.
import { ... } from '@absoluteui/icons';How to use
Section titled “How to use”Components ask for icons by name. This package resolves those names, lets you add or replace icons (including whole third-party libraries such as Lucide, Font Awesome, and Material Symbols), sizes and layers them, and renders them as accessible elements. The Icons guide covers every option in depth.
How do I show an icon in my own markup, at a given size?
Section titled “How do I show an icon in my own markup, at a given size?”renderIcon returns the element components use: decorative by default, an image with an accessible name when you pass label. size takes a theme size ('xs' 0.75rem, 'sm' 1rem, 'md' 1.25rem, 'lg' 1.5rem, 'xl' 2rem) or a CSS length.
import { renderIcon } from '@absoluteui/icons';
const decorative = renderIcon('check', { size: 'lg' });decorative.getAttribute('aria-hidden'); // => 'true'decorative instanceof SVGElement ? decorative.style.fontSize : ''; // => 'var(--aui-icon-size-lg, 1.5rem)'const meaningful = renderIcon('check-circle', { label: 'Approved', size: '20px' });[meaningful.getAttribute('role'), meaningful.getAttribute('aria-label')]; // => ['img', 'Approved']How do I resize the icons of a component, a region, or the whole app?
Section titled “How do I resize the icons of a component, a region, or the whole app?”Set --aui-icon-size on the component or any ancestor: every icon inside follows it (component icons, and those from renderIcon). To change the defaults everywhere, override the theme tokens --aui-icon-size-xs … --aui-icon-size-xl.
import { renderIcon } from '@absoluteui/icons';
const toolbar = document.createElement('div');toolbar.style.setProperty('--aui-icon-size', '1.5rem'); // this region onlydocument.documentElement.style.setProperty('--aui-icon-size-sm', '1.125rem'); // app-wide default for small iconstoolbar.append(renderIcon('search'));How do I use Font Awesome?
Section titled “How do I use Font Awesome?”Install @fortawesome/free-solid-svg-icons (or another Font Awesome SVG package) and convert the icons you use with fromFontAwesome. Only the imported icons are in your bundle. Font Awesome Free icons are licensed CC BY 4.0: keep its attribution.
import { faCalendarDays, faUser } from '@fortawesome/free-solid-svg-icons';import { fromFontAwesome, registerIcons, renderIcon } from '@absoluteui/icons';
registerIcons({ user: fromFontAwesome(faUser), calendar: fromFontAwesome(faCalendarDays) });renderIcon('user').getAttribute('viewBox'); // => '0 0 448 512'If you use Font Awesome’s web font instead, map names to its classes: { kind: 'class', className: 'fa-solid fa-user' }, and load its stylesheet yourself.
How do I use Material Symbols from Google Fonts?
Section titled “How do I use Material Symbols from Google Fonts?”Load the font stylesheet from Google Fonts, allow its hosts in your CSP (webFontHosts.google from @absoluteui/theme), and register icons as ligatures: the element carries the font class and the icon name as text.
import { webFontHosts } from '@absoluteui/theme';import { registerIcons, renderIcon } from '@absoluteui/icons';
const link = document.createElement('link');link.rel = 'stylesheet';link.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200';document.head.append(link);const csp = `style-src 'self' ${webFontHosts.google.styleSrc}; font-src 'self' ${webFontHosts.google.fontSrc}`;
registerIcons({ home: { kind: 'ligature', className: 'material-symbols-outlined', text: 'home' } });const home = renderIcon('home');[home.textContent, home.getAttribute('translate')]; // => ['home', 'no']csp.includes('https://fonts.gstatic.com'); // => trueMaterial Icons (the older font) works the same way with className: 'material-icons'. Both are Apache 2.0 licensed.
How do I use Material Symbols or Material Icons as SVG instead of a font?
Section titled “How do I use Material Symbols or Material Icons as SVG instead of a font?”SVG avoids loading a font and a third-party host. Take the path from the icon’s SVG file (for example from the @material-symbols/svg-400 package, imported as text by your bundler):
import homeSvg from '@material-symbols/svg-400/outlined/home.svg?raw';import { registerIcons, renderIcon } from '@absoluteui/icons';
const viewBox = /viewBox="([^"]+)"/.exec(homeSvg)?.[1] ?? '0 -960 960 960';const d = /\sd="([^"]+)"/.exec(homeSvg)?.[1] ?? '';registerIcons({ home: { kind: 'svg', viewBox, paths: [d] } });renderIcon('home').getAttribute('viewBox'); // => '0 -960 960 960'How do I use Lucide, and make every component use it?
Section titled “How do I use Lucide, and make every component use it?”Convert Lucide’s icon nodes with fromSvgNodes. A provider that maps the names components ask for to Lucide icons switches every component at once; unmapped names fall back to the built-in set.
import { Calendar, ChevronDown, Search, X } from 'lucide';import { fromSvgNodes, resolveIcon, setIconProvider, type IconDefinition } from '@absoluteui/icons';
const lucideIcons: Readonly<Record<string, IconDefinition>> = { close: fromSvgNodes(X), 'chevron-down': fromSvgNodes(ChevronDown), calendar: fromSvgNodes(Calendar), search: fromSvgNodes(Search),};setIconProvider({ resolve: (name) => lucideIcons[name] });resolveIcon('close') === lucideIcons.close; // => trueresolveIcon('check').kind; // => 'svg' // not mapped: the built-in checkLucide is ISC licensed. The same fromSvgNodes works for other sets that publish [tag, attributes] nodes.
How do I layer icons, for a badge or a counter?
Section titled “How do I layer icons, for a badge or a counter?”A layers definition stacks icons and short texts in one icon. Each layer can be scaled, moved (in em), rotated, flipped, placed in a corner, and coloured with a theme tone. Label the whole icon once.
import { renderIcon } from '@absoluteui/icons';
const dot = { kind: 'svg', viewBox: '0 0 24 24', nodes: [['circle', { cx: 12, cy: 12, r: 12 }]] } as const;const events = renderIcon({ kind: 'layers', layers: [ { icon: 'calendar' }, { icon: dot, scale: 0.45, position: 'top-end', tone: 'error' }, { text: '3', position: 'bottom-end', tone: 'error' }, ],}, { label: '3 events today', size: 'xl' });[events.getAttribute('aria-label'), events.children.length]; // => ['3 events today', 3]How do I register an icon provider?
Section titled “How do I register an icon provider?”A provider is asked first for every name. Return a definition for the names you replace and undefined for the rest, which then come from the registry. setIconProvider(null) removes it.
import { builtInIcons, resolveIcon, setIconProvider, type IconDefinition } from '@absoluteui/icons';
const brand: Readonly<Record<string, IconDefinition>> = { close: { kind: 'svg', viewBox: '0 0 20 20', stroke: true, paths: ['M5 5l10 10M15 5L5 15'] },};setIconProvider({ resolve: (name) => brand[name] });resolveIcon('close') === brand.close; // => trueresolveIcon('check') === builtInIcons.check; // => truesetIconProvider(null);resolveIcon('close') === builtInIcons.close; // => trueHow do I change the icon of one component only?
Section titled “How do I change the icon of one component only?”Pass a name or an inline definition in the component’s icons option (each component lists its icon slots in its API reference). Other instances are unaffected.
import { Spinner } from '@absoluteui/components/spinner';
const host = document.createElement('div');document.body.append(host);Spinner.create(host, { label: 'Saving', icons: { spinner: 'refresh' } });What goes wrong?
Section titled “What goes wrong?”Unknown names, unsafe or malformed definitions, and invalid sizes fail loudly, with the icon’s name in the error. Shape nodes accept geometry, fill/stroke (none or currentColor), fill rules, and opacity only: no event handlers, styles, links, or scripts. TypeScript already rejects a size like 'huge'; the run-time check covers values from untyped configuration (the cast below simulates one).
import { fromSvgNodes, registerIcons, renderIcon, resolveIcon } from '@absoluteui/icons';
resolveIcon('no-such-icon'); // => throws ICON_UNKNOWNregisterIcons({ broken: { kind: 'svg', viewBox: '0 0 24', paths: ['M0 0'] } }); // => throws ICON_INVALIDfromSvgNodes([['circle', { cx: 12, onclick: 'alert(1)' }]]); // => throws ICON_INVALIDrenderIcon('check', { size: 'huge' as '1px' }); // => throws ICON_INVALID_SIZEBuilt-in icons
Section titled “Built-in icons”API reference
Section titled “API reference”Functions
Section titled “Functions”fromFontAwesome
Converts a Font Awesome SVG icon definition (for example faUser from
@fortawesome/free-solid-svg-icons) into an AbsoluteUI svg definition (filled with the text
colour). Duotone definitions become one path per layer.
function fromFontAwesome(definition: FontAwesomeIconLike): IconDefinition;Example:
fromFontAwesome({ icon: [448, 512, [], 'f007', 'M224 256a128 128 0 1 0 0-256z'] });// => { kind: 'svg', viewBox: '0 0 448 512', paths: ['M224 256a128 128 0 1 0 0-256z'] }fromSvgNodes
Converts [tag, attributes] shape nodes, the format of Lucide’s lucide package (fromSvgNodes(Users)) and similar
icon sets, into an AbsoluteUI svg definition. Attributes are validated like every other
icon; unsupported ones throw ICON_INVALID.
function fromSvgNodes(nodes: readonly (readonly [string, Readonly<Record<string, string | number | undefined>>])[], options?: FromSvgNodesOptions): IconDefinition;Example:
fromSvgNodes([['circle', { cx: '12', cy: '12', r: '10' }], ['path', { d: 'M12 8v4' }]]).kind; // => 'svg'registerIcons
Register or replace named icons in the built-in registry.
function registerIcons(icons: Readonly<Record<string, IconDefinition>>): void;renderIcon
Render an icon element. Decorative by default; semantic when label is set.
function renderIcon(ref: IconRef, options?: RenderIconOptions): Element;Example:
const icon = renderIcon('calendar', { size: 'lg' });icon.getAttribute('aria-hidden'); // => 'true'icon instanceof SVGElement ? icon.style.fontSize : ''; // => 'var(--aui-icon-size-lg, 1.5rem)'resolveIcon
function resolveIcon(ref: IconRef): IconDefinition;setIconProvider
Set a global icon provider. It is consulted before the registry, so a
corporate icon set can replace every AbsoluteUI icon. null removes it.
function setIconProvider(next: IconProvider | null): void;Constants
Section titled “Constants”builtInIcons
Built-in icon set: original, minimal 24x24 stroke geometry.
const builtInIcons: Readonly<Record<string, IconDefinition>>;Interfaces
Section titled “Interfaces”FontAwesomeIconLike
Shape of a Font Awesome icon definition (@fortawesome/*-svg-icons): icon is
[width, height, ligatures, unicode, pathData]. Typed structurally; no Font Awesome import.
interface FontAwesomeIconLike { readonly icon: readonly [number, number, unknown, unknown, string | readonly string[]];}FromSvgNodesOptions
interface FromSvgNodesOptions { readonly viewBox?: string; readonly stroke?: boolean; readonly strokeWidth?: number;}IconLayer
One layer of a layers icon: an icon or a short text (a counter), optionally transformed,
placed, and coloured. Offsets x/y are in em (fractions of the icon size).
interface IconLayer { readonly icon?: IconRef; readonly text?: string; readonly scale?: number; readonly x?: number; readonly y?: number; readonly rotate?: number; readonly flip?: 'horizontal' | 'vertical' | 'both'; readonly position?: IconLayerPosition; readonly tone?: IconTone; readonly className?: string;}IconProvider
interface IconProvider { resolve(name: string): IconDefinition | undefined;}RenderIconOptions
interface RenderIconOptions { label?: string; className?: string; size?: IconSize; doc?: Document;}IconDefinition
type IconDefinition ={ readonly kind: 'svg'; readonly viewBox: string; readonly paths?: readonly string[]; readonly nodes?: readonly SvgNode[]; readonly stroke?: boolean; readonly strokeWidth?: number;}| { readonly kind: 'factory'; readonly create: (doc: Document) => Element;}| { readonly kind: 'class'; readonly className: string;}| { readonly kind: 'ligature'; readonly className: string; readonly text: string;}| { readonly kind: 'layers'; readonly layers: readonly IconLayer[];};IconLayerPosition
Corner or centre of a layered icon, for badges and counters.
type IconLayerPosition = 'center' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';IconRef
An icon name resolved through the provider/registry, or an inline definition.
type IconRef = string | IconDefinition;IconSize
Theme icon sizes (icon-size-xs 0.75rem … icon-size-xl 2rem), or a CSS length such as '1.125rem' or '20px'.
type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | `${number}${'px' | 'rem' | 'em' | 'pt' | '%'}`;IconTone
Colours a layer can take from the theme.
type IconTone = 'primary' | 'success' | 'warning' | 'error' | 'muted';SvgNode
One SVG shape as [tag, attributes], the format Lucide and many icon sets publish. Geometry
attributes are numbers or numeric strings; fill and stroke may be 'none' or
'currentColor'; fill-rule/clip-rule 'nonzero' or 'evenodd'; opacity 0 to 1.
type SvgNode = readonly [SvgNodeTag, Readonly<Record<string, string | number>>];SvgNodeTag
SVG shape elements an svg definition may contain.
type SvgNodeTag = 'circle' | 'ellipse' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect';