Skip to content

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.

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.

Prop/inputTypeDefaultPurpose
nameIconNamerequired on SimurghIconSelects a kebab-case icon. Named components omit it.
sizenumber | string24Sets SVG width and height. Numbers are pixels; strings may use CSS units.
titlestringnoneGives 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.
mirrorInRtlbooleantrueDisables 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.

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.

The unsuffixed name is the default, broadly applicable metaphor. Suffixes describe a stable visual or container distinction, never a temporary interaction state:

  • -filled is the solid counterpart of the default form and may indicate persistent selection.
  • -circle adds a meaningful circular status container; it is not merely a heavier version.
  • -round describes a materially rounded object rather than routine corner-radius variation.
  • -alt is 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.

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.

Use the unsuffixed name for the default, broadly applicable metaphor. Suffixes describe a stable visual or container distinction rather than a temporary interaction state:

  • -filled is the solid counterpart of an outlined/default icon and is appropriate for persistent selected states.
  • -circle adds a meaningful circular status container; do not use it merely to increase weight.
  • -round describes a materially rounded object, not ordinary corner-radius variation.
  • -alt is 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.

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.

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.

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'; // named
import { SimurghIcon } from '@simurgh-ui/icons/react/dynamic'; // dynamic
import { getIcon, iconGroups } from '@simurgh-ui/icons/catalog'; // category lookup
import arrowRightUrl from '@simurgh-ui/icons/svg/arrow-right'; // raw asset

Run 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.