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.
Overview
-
1
Standard
-
2
Custom
-
3
Skeleton
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
-
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
-
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
-
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
-
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
-
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
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
-
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.
-
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
-
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
-
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
-
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
-
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
-
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.
Accessibility
-
1
Plain Text by Default The label reads as text in content order — no role, no label, no focus.
role="img"with anaria-labelonly when the tag is a standalone indicator whose text alone does not carry the meaning; icons in slots are alwaysaria-hidden="true". -
2
The Remove Button Is the Only Target The root takes
role="group"; the EndSlot<button>carriesaria-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, carriesaria-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.