Icon
A styled, accessible SVG icon. Decorative by default — renders with aria-hidden="true" and no
role. Pass a label to expose it to assistive technology as an image: the icon switches to
role="img" + aria-label automatically.
The examples are organised by layer: the class reference is the standalone
@oriui/css layer, and the Framework API is the @oriui/vue component. Every
example is live — flip its code between HTML (the standalone classes, also your htmx / Astro / Svelte /
plain-HTML usage), Vue; HTML is the default.
Classes
An icon is a block class plus single-class token utilities — one class repoints one token; no separate base class is needed. The Vue props in Framework API map 1:1 to these. There is no variant or radius — an icon takes a size, an optional color, and optional layout modifiers.
| Class | Type | Description |
|---|---|---|
ori-icon | Block | Required base class. Default size (text) and spacing are baked in — a bare block is valid. |
ori-icon_* (size sugar) | Size | text (inherits) · xs · sm · md · lg · xl · xxl — text is the default |
ori-color_* | Color | primary · secondary · success · warn · danger · info · surface · background — omit to inherit |
ori-size-action-space_* | Layout | adds margin equal to the action-space scale for the active size (the spaced opt-in); pair with a size modifier |
ori-icon_inline | Layout | switches to inline-flex with a small em-based margin for flow text |
aria-hidden · role=img | State | decorative by default (aria-hidden=true); a label switches to role=img + aria-label |
Sizes
xs → xxl. The default text means the icon inherits the current font size — use text to keep
an icon visually matched to surrounding copy.
The text default inherits the surrounding font size — the icon below sits inside a sentence and tracks the
paragraph's font-size with no explicit size prop:
<!-- ori-icon_xs / _md / _xxl drive the icon box; aria-hidden because decorative -->
<i class="ori-icon ori-icon_xs" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
<i class="ori-icon ori-icon_md" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
<i class="ori-icon ori-icon_xxl" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
<!-- no size modifier: inherits font size (text default) -->
<i class="ori-icon ori-icon_inline" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
Colors
Every semantic role. surface / background are also available. Omit color to inherit currentcolor from the parent.
<!-- ori-color_<role> repoints the color token in one class -->
<i class="ori-icon ori-icon_lg ori-color_primary" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
<i class="ori-icon ori-icon_lg ori-color_danger" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
Inline
inline switches the icon to inline-flex with a small em-based margin so it flows naturally
inside a sentence or a label without a wrapper element.
<p>
Read the
<i class="ori-icon ori-icon_inline ori-icon_md" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M13,9H11V7H13…" /></svg>
</i>
note carefully.
</p>
Spaced
spaced adds a margin around the icon equal to the action-space scale for the active size — useful
when the icon floats in open space rather than inside a button or label.
<i class="ori-icon ori-icon_lg ori-size-action-space_lg ori-color_primary" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M22,13H13V22H11V13H2V11H11V2H13V11H22V13Z" /></svg>
</i>
Accessible (labelled)
Pass label to make the icon meaningful. The component sets role="img" and aria-label
automatically and removes aria-hidden.
<!-- note: no aria-hidden; role="img" + aria-label carry the name -->
<i class="ori-icon ori-icon_lg" role="img" aria-label="Warning">
<svg viewBox="0 0 24 24"><path d="M12,2A10,10…" /></svg>
</i>
Custom SVG slot
Omit icon and place your own SVG (or any content) in the default slot. The slot content is sized
to 100% × 100% and filled with currentcolor.
<i class="ori-icon ori-icon_lg ori-color_primary" aria-hidden="true">
<svg viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" />
<path d="M12 8v4l3 3" stroke="white" stroke-width="2" fill="none" />
</svg>
</i>
Common patterns
An icon placed beside a status badge — size matches the action row, color follows the semantic role.
<div style="display: flex; align-items: center; gap: 0.5rem">
<i class="ori-icon ori-icon_md ori-color_success" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5…" /></svg>
</i>
<span>Deployed</span>
</div>
Accessibility
The accessibility contract holds across every layer — the standalone classes and the Vue component render the same attributes.
- Decorative by default: renders
<i aria-hidden="true">with no role. Use this mode when the icon sits beside visible text that already communicates its meaning (status rows, labelled buttons, list items with text). - Meaningful icon: pass
label— the component addsrole="img"andaria-labeland removesaria-hidden. Use this mode for standalone icons that carry meaning not expressed in nearby text (e.g. a lone star meaning "favourited"). - When used inside an
OriButton(or any control with its own accessible name), the icon is always decorative — let the button's own label oraria-labelcarry the name. :focus-visibleis not applicable — OriIcon is a presentational element, not interactive.
| Attribute | When set |
|---|---|
aria-hidden="true" | Default; no label prop. |
role="img" | label prop is provided. |
aria-label | Equal to the label prop when provided. |
Framework API
The props, events, and slots of the Vue component. The standalone CSS layer has no component API — its surface is the classes above. (Svelte bindings are planned.)
Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | ThemeColor | — | Semantic color role. Omit to inherit currentcolor from the parent. |
icon | string | — | SVG <path d> string. Renders inside a 24 × 24 viewBox. Omit to use the default slot instead. |
inline | boolean | false | Switches to inline-flex with an em-based margin for use inside text flow. |
label | string | — | Accessible name. When set, adds role="img" and aria-label; removes aria-hidden. |
size | ActionSize | 'text' | Icon box size (xs · sm · md · lg · xl · xxl). text inherits the current font size. |
spaced | boolean | false | Adds action-space margin scaled to the active size. Has no effect when size is not set. |
Events & attributes
OriIcon declares no custom events and does not set inheritAttrs: false, so native attributes
(class, style, data-*, event listeners, …) fall through directly to the rendered <i> element.
A fall-through aria-label alone does not name the icon: when the label prop is unset the
component always sets aria-hidden="true", which removes the element from the accessibility tree and
causes assistive technology to ignore any aria-label on it. The label prop is the only correct
way to name an icon — it sets role="img", aria-label, and removes aria-hidden together.
Slots
| Slot | Description |
|---|---|
default | Custom icon content. When provided, the icon prop is ignored. Slot content is sized 100% × 100% via .ori-icon > *. |