Icon usage and API
Use named components for fixed interface icons and SimurghIcon when the name comes from typed
application data. Both forms render the same SVG definition.
import { ArrowRight, SimurghIcon } from '@simurgh-ui/icons/react';
export function Actions() { return ( <> <ArrowRight size={20} title="Next page" className="next-icon" /> <SimurghIcon name="settings" size="1.25em" aria-hidden="true" /> </> );}Named components accept standard React SVG attributes plus the shared icon props. Refs target the
root SVGSVGElement.
<script setup lang="ts">import { ArrowRight, SimurghIcon } from '@simurgh-ui/icons/vue';</script>
<template> <ArrowRight :size="20" title="Next page" class="next-icon" /> <SimurghIcon name="settings" size="1.25em" aria-hidden="true" /></template>Unrecognized attributes and listeners are forwarded to the root SVG.
Angular
Section titled “Angular”import { Component } from '@angular/core';import { ArrowRight, SimurghIcon } from '@simurgh-ui/icons/angular';
@Component({ standalone: true, imports: [ArrowRight, SimurghIcon], template: ` <simurgh-arrow-right-icon [size]="20" title="Next page" class="next-icon" data-state="ready" /> <simurgh-icon name="settings" size="1.25em" /> `,})export class Actions {}Angular named components use selectors of the form simurgh-<name>-icon. Classes, inline styles,
data-*, aria-*, role, and tabindex placed on an Angular icon host are mirrored to its root
SVG and stay synchronized when bindings change.
Shared component props
Section titled “Shared component props”| Prop/input | Type | Default | Purpose |
|---|---|---|---|
name | IconName | required on SimurghIcon | Selects a kebab-case icon. Named components omit it. |
size | number | string | 24 | Sets SVG width and height. Numbers are pixels; strings may use CSS units. |
title | string | none | Gives a standalone informative icon an accessible name and role="img". |
direction | 'ltr' | 'rtl' | nearest dir / :dir() | Overrides the direction used for automatic mirroring, including across portals. |
mirrorInRtl | boolean | true | Disables automatic mirroring when a directional drawing represents a physical direction. |
colorMode | 'duotone' | 'currentColor' | 'duotone' | Uses authored fills or inherits one interface color from CSS. |
All adapters support root SVG classes, styles, data attributes, and ARIA attributes. React refs target the root SVG; Vue forwards fallthrough attributes; Angular mirrors presentation attributes from its component host to the root SVG.
Styling and sizing
Section titled “Styling and sizing”Icons use their authored duotone colors by default. Set colorMode="currentColor" when an icon
should inherit the foreground of a button, link, navigation item, or status treatment. Duotone mode
also exposes --simurgh-icon-primary and --simurgh-icon-secondary, retaining each authored fill as
the fallback. Use size for routine sizing and CSS on the root SVG for layout, opacity, transforms,
or state transitions.
.toolbar-icon { flex: none; inline-size: 1.25rem; block-size: 1.25rem; color: var(--action-foreground);}
.toolbar-button:disabled .toolbar-icon { opacity: 0.45;}
.brand-icon { --simurgh-icon-primary: var(--brand-strong); --simurgh-icon-secondary: var(--brand-accent);}<ArrowRight colorMode="currentColor" className="toolbar-icon" aria-hidden="true" /><Verified className="brand-icon" title="Verified account" />Avoid overriding individual generated paths: their count, colors, and geometry are implementation details rather than stable styling hooks.
Variant naming policy
Section titled “Variant naming policy”The unsuffixed name is the default, broadly applicable metaphor. Suffixes describe a stable visual or container distinction, never a temporary interaction state:
-filledis the solid counterpart of the default form and may indicate persistent selection.-circleadds a meaningful circular status container; it is not merely a heavier version.-rounddescribes a materially rounded object rather than routine corner-radius variation.-altis reserved for a genuinely different conventional metaphor when a more semantic name is unavailable.
Use CSS color or colorMode for hover, pressed, disabled, selected, and destructive treatments.
Do not create icon-name variants for transient UI states.
Contrast and forced colors
Section titled “Contrast and forced colors”Interface icons must reach at least 3:1 against their immediate background in each state. The
Simurgh semantic foreground/background pairs are regression-tested for light and dark normal,
selected, destructive, success, warning, and disabled contexts. Prefer currentColor in controls
so icons inherit the same reviewed foreground as their label.
In Windows forced-colors mode, currentColor follows the user’s system palette. Do not replace it
with an authored fill or disable forced-color adjustment. Keep decorative icons hidden and retain a
visible text label or accessible name when color or shape conveys status.
Variant naming policy
Section titled “Variant naming policy”Use the unsuffixed name for the default, broadly applicable metaphor. Suffixes describe a stable visual or container distinction rather than a temporary interaction state:
-filledis the solid counterpart of an outlined/default icon and is appropriate for persistent selected states.-circleadds a meaningful circular status container; do not use it merely to increase weight.-rounddescribes a materially rounded object, not ordinary corner-radius variation.-altis reserved for a genuinely different conventional metaphor when a more semantic name is unavailable.
Prefer CSS color or colorMode for hover, pressed, disabled, and destructive states. Do not create
new icon-name variants for transient UI styling.
Framework-neutral API
Section titled “Framework-neutral API”import { getIcon, iconGroups, iconNames, renderIconSvg,} from '@simurgh-ui/icons';
const definition = getIcon('home');const navigationNames = iconGroups.landmarks;const markup = renderIconSvg('arrow-right', { size: 20, title: 'Next page', direction: 'rtl',});IconDefinition exposes name, group, direction, viewBox, transform, and paths for custom
renderers. iconNames and IconName are the canonical runtime and compile-time name lists.
Static SVG files
Section titled “Static SVG files”Use the wildcard export when a tool accepts an asset URL rather than a framework component:
import homeUrl from '@simurgh-ui/icons/svg/home';Exact asset-import syntax depends on your bundler. When it cannot resolve package wildcard assets,
copy the required SVG during your build rather than linking into node_modules at runtime.
Import strategy and bundle cost
Section titled “Import strategy and bundle cost”Use a named subpath for a fixed icon. Dynamic and category-level APIs are discovery tools: because a runtime name can select any definition, bundlers must retain the complete catalog. A raw SVG has the smallest adapter cost but leaves sizing, color, RTL behavior, and accessibility to your code.
| Strategy | Gzip | Brotli | Definitions retained | Consequence |
|---|---|---|---|---|
| Named component | 1002 B | 862 B | 1 | Best component tree-shaking: only the selected definition and shared React adapter remain. |
| Dynamic component | 257.5 KiB | 218.4 KiB | 474 | Runtime name selection retains the complete definition catalog. |
| Category lookup | 258.8 KiB | 219.7 KiB | 474 | Runtime category traversal retains the complete catalog even when one group is selected. |
| Raw SVG asset | 469 B | 398 B | 1 | Ships one authored asset and no framework adapter; behavior and accessibility are consumer-owned. |
Measured 2026-08-18 with esbuild, gzip level 9, Brotli defaults. Scenario: One Arrow Right icon; React is external for component cases. Values cover generated output only, not the external React runtime or HTTP framing.
Measured examples:
import { ArrowRight } from '@simurgh-ui/icons/react/arrow-right'; // namedimport { SimurghIcon } from '@simurgh-ui/icons/react/dynamic'; // dynamicimport { getIcon, iconGroups } from '@simurgh-ui/icons/catalog'; // category lookupimport arrowRightUrl from '@simurgh-ui/icons/svg/arrow-right'; // raw assetRun node scripts/measure-icon-import-strategies.mjs in the repository to reproduce the table. Do
not compare these generated bytes with a full application chunk: framework runtimes, shared chunks,
and compression dictionaries change the application-level result.
Last verified on 2026-08-13 against Simurgh registry 0.1.1.