Tag
A compact label for categorising, filtering, or annotating content — status chips, keyword
badges, and removable filter pills. State is expressed through real attributes: aria-disabled
disables the tag and its close button without removing it from the DOM.
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
A tag is a block class plus single-class token utilities — one class repoints one token, no base class needed. The Vue props in Framework API map 1:1 to these.
| Class | Type | Description |
|---|---|---|
ori-tag | Block | Required base class. |
ori-variant_* | Style | fill · tonal · outline · text · plain |
ori-color_* | Color | primary · secondary · success · warn · danger · info · surface |
ori-font-size_* | Size | xs · sm · md · lg · xl · xxl — drives the label scale |
ori-size-radius_* | Radius | zero · xs · sm · md · lg · xl · rounded |
ori-tag__icon | Part | icon element (prepend or append) |
ori-tag__text | Part | label text element |
ori-tag__close · ori-tag__close-icon | Part | close button and its icon (present when closable) |
aria-disabled=true | State | real attribute — dims the tag and blocks pointer events |
Like Button, the non-fill variants (the default tonal included) paint the label with the AA-safe
--ori-color-text tone rather than the raw role — see
Design tokens.
Variants
Five visual styles, all driven by the ori-variant_* single-class token.
<span class="ori-tag ori-variant_fill ori-color_primary ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">Fill</span>
</span>
<!-- swap the variant: ori-variant_fill → _tonal / _outline / _text / _plain -->
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">Tonal</span>
</span>
Colors
Every semantic role. Variant and color compose freely.
<span class="ori-tag ori-variant_tonal ori-color_danger ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">danger</span>
</span>
Variant x color compose freely — e.g. a filled success tag or an outlined danger one:
<span class="ori-tag ori-variant_fill ori-color_success ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">Published</span>
</span>
Sizes
xs → xxl. The size drives the label scale via ori-font-size_*. Default is sm.
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_xs ori-size-radius_rounded">
<span class="ori-tag__text">xs</span>
</span>
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_lg ori-size-radius_rounded">
<span class="ori-tag__text">lg</span>
</span>
Radius
From zero (square) to the default rounded (pill).
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_sm ori-size-radius_zero">
<span class="ori-tag__text">zero</span>
</span>
With icons
prependIcon places an icon before the label; appendIcon places one after. Both accept an SVG
path string. They can be used together.
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_sm ori-size-radius_rounded">
<i class="ori-icon ori-tag__icon" aria-hidden="true">
<svg viewBox="0 0 24 24"><path d="M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z" /></svg>
</i>
<span class="ori-tag__text">Verified</span>
</span>
Closable
closable appends a close button. Clicking it emits a close event — your handler removes the tag.
closeLabel sets the button's aria-label (default Remove).
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">React</span>
<button type="button" class="ori-tag__close" aria-label="Remove">
<i class="ori-icon ori-tag__close-icon" aria-hidden="true">
<svg viewBox="0 0 24 24">
<path d="M6.4 19 5 17.6l5.6-5.6L5 6.4 6.4 5l5.6 5.6L17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6Z" />
</svg>
</i>
</button>
</span>
Disabled
disabled applies aria-disabled="true" to the root span, dimming the tag and blocking pointer
events including the close button.
<span class="ori-tag ori-variant_tonal ori-color_primary ori-font-size_sm ori-size-radius_rounded" aria-disabled="true">
<span class="ori-tag__text">Archived</span>
</span>
Common patterns
A filter chip list and a status badge in a table row — the everyday compositions.
<!-- filter chip list -->
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem">
<span class="ori-tag ori-variant_tonal ori-color_success ori-font-size_sm ori-size-radius_rounded">
<span class="ori-tag__text">Vue</span>
<button type="button" class="ori-tag__close" aria-label="Remove">
<i class="ori-icon ori-tag__close-icon" aria-hidden="true">
<svg viewBox="0 0 24 24">
<path
d="M6.4 19 5 17.6l5.6-5.6L5 6.4 6.4 5l5.6 5.6L17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6Z"
/>
</svg>
</i>
</button>
</span>
</div>
Accessibility
The accessibility contract holds across every layer — the standalone classes and the Vue component render the same attributes.
- The root element is a
<span>(non-interactive). When the tag is purely decorative or informational, no additional role is required. disabledsetsaria-disabled="true"(not the booleandisabled) on the root span — the tag stays in the accessibility tree. The nested close<button>gets the booleandisabledattribute so it is unreachable via keyboard when the tag is disabled.- The close button has an explicit
aria-label(defaultRemove); it is a real<button type="button">with a visible:focus-visiblering. - Icon elements inside the tag carry
aria-hidden="true"— they are decorative. - When tags are part of an interactive group (e.g. a filter chip list), wrap the group in an element
with
role="group"and anaria-labeldescribing the set (e.g.aria-label="Active filters").
| Key | Element | Action |
|---|---|---|
Tab | Close button | Moves focus to the close button. |
Enter | Close button | Activates the close button (emits close). |
Space | Close button | Activates the close button (native). |
Framework API
The props, events, slots, and attributes 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 |
|---|---|---|---|
appendIcon | string | — | SVG path for an icon rendered after the label. |
closable | boolean | false | Shows a close button that emits close when clicked. |
closeLabel | string | 'Remove' | aria-label for the close button. |
color | ThemeColor | 'primary' | Semantic role: primary · secondary · success · warn · danger · info · surface. |
disabled | boolean | false | Sets aria-disabled="true" on the root and disabled on the close button. |
prependIcon | string | — | SVG path for an icon rendered before the label. |
radius | RadiusSize | 'rounded' | Corner radius (zero · xs · sm · md · lg · xl · rounded). |
size | ActionSize | 'sm' | Label scale (xs · sm · md · lg · xl · xxl). |
text | string | — | Tag label. Alternatively use the default slot. |
variant | 'fill' | 'tonal' | 'outline' | 'text' | 'plain' | 'tonal' | Visual style. |
Events & attributes
| Event | Payload | Description |
|---|---|---|
close | — | Emitted when the close button is clicked (closable only). |
OriTag does not set inheritAttrs: false, so any extra attributes (class, data-*,
aria-label, …) fall through to the root <span>.
Slots
| Slot | Description |
|---|---|
prepend | Decorator before the label. Falls back to the prependIcon <ori-icon> when not provided. |
default | Replaces the text prop content. Rendered inside ori-tag__text; use for rich labels. |
append | Decorator after the label. Falls back to the appendIcon <ori-icon> when not provided. |