v3.1.0
Tag

A compact static label for categorization, status, and metadata. One size, two presets — Standard with a fixed six-value Style axis and Custom with free colour tokens — plus optional icon slots on either side of the text.

-- -- -- 3.1.0
Label

Overview

  • 1
    Standard
  • 2
    Custom
  • 3
    Skeleton
Label
1
NEW
2
3

States

Tag is non-interactive — Standard is the only rest form; there is no pressed, hover, or focus state. The Style axis below is a design-time choice, six values with fixed tokens each. The border token in each block is consumed only while the tag--border modifier is present (see the Border block at the end).

Surface

Label
1
2
  • 1
    Fill --background-secondary — the neutral default on any light surface.
  • 2
    Content --text-and-icon-primary — label and both icons, via currentColor.Body/Compact Body — the text style.
  • Border --border-default — only with tag--border.

Brand

Label
1
2
  • 1
    Fill --background-brand — the drive-green emphasis.
  • 2
    Content --text-and-icon-always-dark — dark content on the brand fill in both themes.Body/Compact Body — the text style.
  • Border --surface-overlay — only with tag--border.

Color

Label
1
2
  • 1
    Fill --pastel-drive-green2 — the soft pastel tint.
  • 2
    Content --text-and-icon-primary — the content colour.Body/Compact Body — the text style.
  • Border --surface-overlay — only with tag--border.

Inverse

Label
1
2
  • 1
    Fill --background-inverse-primary — a dark pill on the light theme, a light pill on the dark.
  • 2
    Content --text-and-icon-inverse-primary — the counter-phase content.Body/Compact Body — the text style.
  • Border --surface-white-overlay — only with tag--border.

Disabled

Label
1
2
  • 1
    Fill --surface-white-overlay — a near-transparent overlay: the ghost form is carried by the dimmed content.
  • 2
    Content --text-and-icon-disabled — the dimmed content.Body/Compact Body — the text style.
  • Border --surface-overlay — only with tag--border.
  • Visual only Tag owns no interaction to disable — the style dims the look, nothing else changes.

Skeleton

1
  • 1
    Fill --skeleton-on-white — the loading placeholder fill.
  • Empty box --sp-s56 × --sp-s24 — no label, no slots, no border. The sweep is documented under Animation.

Border

Label
Label
Label
1
  • 1
    Off by default The border is a separate layer, hidden in the master; tag--border shows it. An inset 1dp stroke — the box is the same size with and without it, so toggling never shifts the layout.
  • Per-style token --border-default — Surface.--surface-overlay — Brand, Color, Disabled.--surface-white-overlay — Inverse.

Anatomy

A horizontal autolayout of three content parts plus a hidden border layer. Only the label is required; the root passes its content colour to every part via currentColor.

Label
1
2
3
  • 1
    StartSlot --sp-s16 — an IconContainer slot, optional. Class tag__slot--start.
  • 2
    Label Body/Compact Body — the required text, single line.--sp-s2 — the label's own side padding, both sides (Figma's TextContainer).
  • 3
    EndSlot --sp-s16 — an IconContainer slot, optional. Class tag__slot--end. Hosts the remove button when the composition needs one.
  • Border layer An inset 1dp stroke, hidden by default — tag--border shows it. Drawn inside the box: no layout shift.

Layout

One size, hugging both axes: --sp-s16 content plus twice --sp-s4 padding makes 24 at 100%. There are no per-side padding switches — the padding is uniform and the label brings its own side padding, so text lands --sp-s6 from a bare edge and --sp-s2 from an icon by construction. Every SP-bound value scales with the SP mode (100 / 130 / 150%); the 1dp border is the one exception.

Geometry

Label
1
2
3
4
  • 1
    Corner radius --sp-s10 — all four corners.
  • 2
    Padding --sp-s4 — uniform, all four sides.--sp-s0 — the gap between parts: the label's own padding is the visual gap.
  • 3
    Icon slot --sp-s16 — both slots, square.
  • 4
    Label padding --sp-s2 — on the label itself, both sides.
  • Skeleton box --sp-s56 × --sp-s24 — fixed; it replaces the content box entirely.
  • Border 1dp, always — the one value that never scales with the SP mode; drawn inside the box.

RTL

Label LTR — StartSlot leads
Label RTL — the row reverses, the DOM does not
  • Off by default The Figma set carries explicit RTL=On variants for every Style; on the web dir="rtl" reverses the flex row — StartSlot renders on the right, EndSlot on the left.
  • Nothing to mirror The padding is symmetric and the label's side padding is on both sides, so geometry survives the flip untouched.
  • Icons Non-directional glyphs stay upright; directional icons (arrow, chevron, back) mirror per the icon's own RTL variant.

Animation

Motion follows the motion system. Tag itself is static — it declares no motion tokens; the composition that mounts and unmounts it consumes the Transforming Fast pair, and the live patterns below consume DS-wide tokens from motion.css.

Enter / Exit

Label
Live — enter, hold, exit, on a loop
  • General var(--transforming-enter-fast) — appear: opacity + a small scale, 150 ms.var(--transforming-exit-fast) — disappear: the same pair back, 100 ms.Only opacity and transform take part — the demo stays on the compositor.
  • Reduced motion Handled at the token: motion.css zeroes every --transforming-* inside prefers-reduced-motion: reduce — the tag then appears and leaves instantly, with no component override.

Remove press

Removable
Live — press the ✕: highlight, then exit; it returns for the next try
  • pushHighlight var(--component-push-highlight) — the press tint on the EndSlot button, background only, no scale. The tag root never animates a press: only the button is interactive.
  • Exit on remove var(--transforming-exit-fast) — the removed tag leaves on the same exit pair.

Skeleton sweep

Live — the DS shimmer sweep; the container carries aria-busy
  • Shimmer var(--pattern-shimmer) — the DS loop: 1200 ms, linear, infinite.--skeleton-wave — the gradient band sweeping over --skeleton-on-white.Under reduced motion the token zeroes out and the box stays static.

Usage

Use it for metadata that describes nearby content: category labels on cards and cells, status marks in histories and trip details, "New" / "Sale" / "Verified" annotations, the decoration slot of a DecorateContainer composition.

  • 1
    A label, never a control Nothing on a Tag is tappable and nothing waits for the user. The one sanctioned interaction is the EndSlot remove button in filter-style compositions — and the button, not the tag, is the control.
  • 2
    Single line, hugging Copy that needs a second line, or a numeric counter, belongs elsewhere — text in a different surface, a count in an Indicator.
Trip to the airport Verified
✓ A status mark beside the content it describes
Order cancelled Restore order
✕ An action dressed as a label — that is a Button

Accessibility

Verified Plain text — no role, no focus
Verified Removable — only the button is exposed
1
2
  • 1
    Plain Text by Default The label reads as text in content order — no role, no label, no focus. role="img" with an aria-label only when the tag is a standalone indicator whose text alone does not carry the meaning; icons in slots are always aria-hidden="true".
  • 2
    The Remove Button Is the Only Target The root takes role="group"; the EndSlot <button> carries aria-label="Remove {label}" and a 44 × 44 touch target extended past the visible s16 glyph. A real <button> already synthesizes a click on Enter and Space — adding a keydown handler fires the remove twice.
  • Disabled Stays Silent No aria-disabled: disabled is a visual style on a non-interactive element — announcing "disabled" would promise something to enable. TalkBack and VoiceOver read the dimmed label as ordinary text.
  • Skeleton Is Hidden aria-hidden="true" on the empty box; the loading container, not the tag, carries aria-busy="true".
  • Inside a Focusable Cell The Cell takes the focus and the name; the tag inside is aria-hidden="true" when its text is redundant with the Cell's accessible name.