Menu


Tag


A small label naming a category, with an optional leading icon or picture and remove control; pressable, it opens something about what it names.

Customize the preview


Choices
Show
Flags
View
Design

Options


Tag options
ChoiceValuesDefaultWhat it does
tonesmbk-tag--tone-<value>defaultbrandoutlineinfosuccessdangerwarningdefault
A see-through gray that shows on every surface, brand, outlined, or one of the four feedback families on their subtle surfaces.
pressablesmbk-tag--pressableOn or offOff
The tag is a button that opens something about what it names, such as a card, with the hover, pressed and focus looks in the tag's own shape. The wrapper sets it when given onClick, as a popover's opener is; plain markup sets it on a button.

Partssmbk-tag__iconsmbk-tag__leading-contentsmbk-tag__labelsmbk-tag__remove

Examples


Usage

A plain tag in the default tone.

Design

Tones

Seven tones: a neutral gray, brand, outline and the four feedback colors.

DraftFeaturedArchivedBetaStableDeprecatedExperimental

With icon

An icon before the label.

DesignFeatured

Removable

The remove control appears when a handler is given; its small cross sits in a box large enough to press.

ReactTypeScriptDesign

With a picture

The page's own picture, here an inline SVG, in the icon's place at the icon's size, in the tag's text color.

PlatformGrowthResearch

Opens a card

As a popover's opener the tag is a button that opens a card about what it names, with the pointer, hover, pressed and focus looks in the tag's own shape. Each tag is a Tab stop of its own.

Guidelines


Purpose

A small label that names a category, a topic or a keyword on the thing it sits on. It reads as metadata, which is what separates it from a badge (a state) and from a chip (a choice). A pressable tag opens something about what it names, such as a small card about a person or a place.

When to use

  • Topics on an article or a card.
  • Keywords a person has attached to something and may take off again.
  • A row of things that each open a small card about themselves when pressed, such as the members of a team or the stops on a route.

When not to use

  • For status. Use a badge; the feedback tones here are for categories that happen to be colored, not for state.
  • For a choice a person toggles, or a filter. Use a chip.
  • For a press that goes to another page or does something. Use a link or a button.

Usage rules

Do

  • Keep the label to one or two words, so the tag stays a glance.
  • Make a tag pressable when a press opens something about what it names, such as a card about a person or a place.

Don't

  • Make a tag pressable to filter a list or choose an option. That is a chip.
  • Make a tag both pressable and removable. Open what it names from the tag, and remove it somewhere else.
BetaStable
Do

Keep a tag to one or two words, so it reads at a glance.

Available to early access customers only
Don't

A long tag becomes a sentence squeezed into a label, slow to read.

Anatomy

  • The block, a short rounded rectangle of fixed height, on the same scale as the badge and the chip. The default tone is a see-through gray with no edge, so it shows on any surface. A pressable tag is a button drawn the same.
  • The icon part, an optional small glyph before the label.
  • The leading content part, the page's own small picture in the icon's place, at the icon's size. An inline SVG or an image fills the icon's box, and any other element is held to it. A tag has the icon or the picture, not both.
  • The label part, text in sentence case in the small label style.
  • The remove part, an optional small cross control, inside a box large enough to press that adds no width.

Behavior

None of its own. The remove control, when present, calls back.

Given a press handler, the tag is a button, and as a popover's opener it gets one from the popover. It keeps its shape, height and type, and takes the pointer, a hover look, a pressed look that sinks in and a focus ring round it. A pressable tag is never removable: given both, it is drawn removable and warns in development, because its remove control would be a button inside a button.

On a touch screen the remove cross keeps its box, and a pressable tag keeps its size, each taking an invisible press area round it, out to the comfortable touch target.

Accessibility


What it does for you

  • The label is read as text.
  • The remove control is a real button. It is at least 24 by 24 pixels, the least a press needs, though its cross is small.
  • The remove control's focus ring is drawn round the cross, and on a brand tag in the inverse focus color, so it shows on the fill.
  • A pressable tag is a real button, named by its words, and its focus ring is drawn round the tag. As a popover's opener it says that it opens a dialog and whether that is open.
  • The icon is decorative.
  • On a touch screen the remove cross and a pressable tag each take an invisible press area round them, out to the comfortable touch target.

What you must do

  • Give the remove control an accessible name saying what it removes. Without one the wrapper warns in development and names it "Remove" and the tag's words.
  • Hide a picture of your own that only repeats the tag's words (aria-hidden="true" on an SVG, an empty alt on an image). Give it words of its own when it says something the label does not.
  • Never put a pressable tag inside a link or another button.

How to test

  • Tab to the remove control: the focus ring shows round the cross, on a brand tag too, in both themes and in a forced-color mode. Press Enter, then Space: each calls back.
  • Tab to a pressable tag: the focus ring shows round it. Press Enter, then Space: each opens what it names.
  • With a screen reader, the label is read as text and the remove control as a button by what it removes; a pressable tag is read as a button by its words.
  • On a touch screen, a press just outside the cross still removes the tag, and a press just outside a pressable tag still presses it.

Keyboard

Tag keys
KeyWhat it does
Tab
Moves focus to a pressable tag, or to the remove control when the tag has one. Each pressable tag in a row is a stop of its own.
EnterorSpace
Presses the pressable tag, or the remove control, which calls back.

Source


The files the tag is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
tag.css
/* smbk-tag — Tag. Figma "Tag" 4088:12242.
 * 24 tall on the pill scale, Label SM in sentence case, a 12 icon and cross.
 * The default tone is a see-through gray with no edge and no shadow, so it
 * shows on every surface. Figma draws the edge inside the tag, so the padding
 * gives the edge's width back, and every tag draws one, clear where its tone
 * has none, so all are the same size. A pressable tag is a button drawn the
 * same, with a control's hover, pressed and focus looks (the end of this file). */

.smbk-tag {
  /* The default tone; each feedback tone sets these again below (the tone recipe). */
  --smbk-tone-surface: var(--smbk-color-surface-neutral-subtle);
  --smbk-tone-border: transparent;
  --smbk-tone-text: var(--smbk-color-text-subtle);
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: var(--smbk-space-inline-xs);
  height: var(--smbk-size-mark-lg);
  padding: 0 calc(var(--smbk-space-inset-md) - var(--smbk-border-width-hairline));
  border: var(--smbk-border-width-hairline) solid var(--smbk-tone-border);
  border-radius: var(--smbk-radius-control-sm);
  background: var(--smbk-tone-surface);
  color: var(--smbk-tone-text);
  font-family: var(--smbk-typography-label-sm-font-family);
  font-size: var(--smbk-typography-label-sm-font-size);
  font-weight: var(--smbk-typography-label-sm-font-weight);
  line-height: var(--smbk-typography-label-sm-line-height);
  letter-spacing: var(--smbk-typography-label-sm-letter-spacing);
  text-transform: var(--smbk-typography-label-sm-text-transform);
  white-space: nowrap;
}

.smbk-tag__icon {
  font-size: var(--smbk-size-icon-xs);
}

/* The page's own picture in the icon's place: a box the icon's size, an svg or an img filling it, and any other element
   of the page's own held to it however large it is drawn elsewhere. An svg that fills or strokes with currentColor
   takes the tag's text color, as the icon does. */
.smbk-tag__leading-content {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: var(--smbk-size-icon-xs);
  height: var(--smbk-size-icon-xs);
}

.smbk-tag__leading-content > * {
  max-width: 100%;
  max-height: 100%;
}

.smbk-tag__leading-content > :is(svg, img) {
  display: block;
  width: 100%;
  height: 100%;
}

/* The cross sits inside a 24 px box, the least a press needs; the box reaches past the cross into the gap
   and the padding, so it adds no width and the cross sits where Figma draws it. The focus ring is drawn
   on the cross's own edge.
   The box is the small press box, with its press area on a touch screen, shared in press-box/press-box.css. */
.smbk-tag__remove {
  margin: calc((var(--smbk-size-icon-xs) - var(--smbk-size-target-min)) / 2);
}

.smbk-tag__remove > .smbk-icon {
  font-size: var(--smbk-size-icon-xs);
  border-radius: var(--smbk-radius-full);
}

.smbk-tag__remove:focus-visible {
  outline: none;
}

.smbk-tag__remove:focus-visible > .smbk-icon {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: 0;
}

/* ---- tone ---- */

.smbk-tag--tone-brand {
  background: var(--smbk-color-surface-brand);
  border-color: var(--smbk-color-border-rim-subtle);
  color: var(--smbk-color-text-on-brand);
  box-shadow: var(--smbk-elevation-raised);
}

/* The focus color would not show on the brand fill, so the ring there takes the inverse focus color. */
.smbk-tag--tone-brand .smbk-tag__remove:focus-visible > .smbk-icon {
  outline-color: var(--smbk-color-border-focus-inverse);
}

.smbk-tag--tone-outline {
  background: transparent;
  border-color: var(--smbk-color-border-strong);
}

/* The feedback tones: the tone recipe, each family's subtle surface inside its pale edge. */

.smbk-tag--tone-info { --smbk-tone-surface: var(--smbk-color-feedback-info-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-info-border-subtle); --smbk-tone-text: var(--smbk-color-feedback-info-text-on-subtle); }
.smbk-tag--tone-success { --smbk-tone-surface: var(--smbk-color-feedback-success-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-success-border-subtle); --smbk-tone-text: var(--smbk-color-feedback-success-text-on-subtle); }
.smbk-tag--tone-danger { --smbk-tone-surface: var(--smbk-color-feedback-danger-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-danger-border-subtle); --smbk-tone-text: var(--smbk-color-feedback-danger-text-on-subtle); }
.smbk-tag--tone-warning { --smbk-tone-surface: var(--smbk-color-feedback-warning-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-warning-border-subtle); --smbk-tone-text: var(--smbk-color-feedback-warning-text-on-subtle); }

/* ---- pressable: a button that opens something about what it names ----
   The tag's own shape, height, corner and type, never the chip's pill, with the chip's pointer, hover, pressed and
   focus looks. The button's own look is reset, so a button and a span draw the same tag. The hover and pressed looks
   go through the tone recipe: the default tone takes the hover and pressed fills, a feedback tone keeps its surface and
   takes its family's full edge for its pale one; brand and outline set their colors directly, as they do at rest.
   Pressed, every tone sinks in. On a touch screen the tag takes an invisible press area round it, out to the
   comfortable target (press-box/press-box.css). */

.smbk-tag--pressable {
  margin: 0;
  cursor: pointer;
  text-align: start;
  text-decoration: none;
  -webkit-user-select: none;
  user-select: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.smbk-tag--pressable:focus-visible {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: var(--smbk-focus-ring-offset);
}

@media (hover: hover) {
  .smbk-tag--pressable:hover { --smbk-tone-surface: var(--smbk-color-surface-hover); }
  .smbk-tag--pressable.smbk-tag--tone-info:hover { --smbk-tone-surface: var(--smbk-color-feedback-info-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-info-border); }
  .smbk-tag--pressable.smbk-tag--tone-success:hover { --smbk-tone-surface: var(--smbk-color-feedback-success-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-success-border); }
  .smbk-tag--pressable.smbk-tag--tone-danger:hover { --smbk-tone-surface: var(--smbk-color-feedback-danger-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-danger-border); }
  .smbk-tag--pressable.smbk-tag--tone-warning:hover { --smbk-tone-surface: var(--smbk-color-feedback-warning-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-warning-border); }

  .smbk-tag--pressable.smbk-tag--tone-brand:hover {
    background: var(--smbk-color-action-brand-background-hover);
    border-color: var(--smbk-color-action-brand-border-hover);
  }

  .smbk-tag--pressable.smbk-tag--tone-outline:hover {
    background: var(--smbk-color-action-outline-background-hover);
    border-color: var(--smbk-color-action-outline-border-hover);
  }
}

.smbk-tag--pressable:active {
  --smbk-tone-surface: var(--smbk-color-action-default-background-pressed);
  box-shadow: var(--smbk-elevation-inset-strong);
}

.smbk-tag--pressable.smbk-tag--tone-info:active { --smbk-tone-surface: var(--smbk-color-feedback-info-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-info-border); }
.smbk-tag--pressable.smbk-tag--tone-success:active { --smbk-tone-surface: var(--smbk-color-feedback-success-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-success-border); }
.smbk-tag--pressable.smbk-tag--tone-danger:active { --smbk-tone-surface: var(--smbk-color-feedback-danger-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-danger-border); }
.smbk-tag--pressable.smbk-tag--tone-warning:active { --smbk-tone-surface: var(--smbk-color-feedback-warning-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-warning-border); }

.smbk-tag--pressable.smbk-tag--tone-brand:active {
  background: var(--smbk-color-action-brand-background-pressed);
  border-color: var(--smbk-color-action-brand-border-hover);
}

.smbk-tag--pressable.smbk-tag--tone-outline:active {
  background: var(--smbk-color-action-outline-background-pressed);
  border-color: var(--smbk-color-action-outline-border-hover);
}
Tokens it reads
Tag tokens
Token and CSSValuePreviewFoundation
size.target.min--smbk-size-target-min24pxSize
size.target.comfortable--smbk-size-target-comfortable44pxSize
color.surface.neutral-subtle--smbk-color-surface-neutral-subtlelight: #373d431adark: #606a7533changes with themeColor
color.text.subtle--smbk-color-text-subtlelight: #4e555edark: #9ba5b1changes with themeColor
space.inline.xs--smbk-space-inline-xs4pxSpacing
size.mark.lg--smbk-size-mark-lg24pxSize
space.inset.md--smbk-space-inset-mdcomfortable: 8pxcompact: 6pxchanges with densitySpacing
border-width.hairline--smbk-border-width-hairline1pxBorder width
radius.control.sm--smbk-radius-control-sm4pxRadius
typography.label-sm--smbk-typography-label-sm-font-family--smbk-typography-label-sm-font-size--smbk-typography-label-sm-font-weight--smbk-typography-label-sm-line-height--smbk-typography-label-sm-letter-spacing--smbk-typography-label-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 12pxfontWeight: 500lineHeight: 1.4letterSpacing: 0px

The quick brown fox

Typography
size.icon.xs--smbk-size-icon-xs12pxSize
radius.full--smbk-radius-full9999pxRadius
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
color.surface.brand--smbk-color-surface-brand#cc0d0dColor
color.border.rim-subtle--smbk-color-border-rim-subtlelight: #ffffff33dark: #ffffff08changes with themeColor
color.text.on-brand--smbk-color-text-on-brand#f9fafbColor
elevation.raised--smbk-elevation-raisedlight: 0px 2px 8px 1px #373d431a, 0px 1px 2px 0px #373d431adark: 0px 2px 8px 1px #00000026, 0px 1px 2px 0px #00000026Elevation
color.border.focus-inverse--smbk-color-border-focus-inverse#f9fafbColor
color.border.strong--smbk-color-border-stronglight: #9ba5b1dark: #373d43changes with themeColor
color.feedback.info.surface-subtle--smbk-color-feedback-info-surface-subtlelight: #e3ebfedark: #162352changes with themeColor
color.feedback.info.border-subtle--smbk-color-feedback-info-border-subtlelight: #b8ccffdark: #213583changes with themeColor
color.feedback.info.text-on-subtle--smbk-color-feedback-info-text-on-subtlelight: #2f4ab8dark: #b8ccffchanges with themeColor
color.feedback.success.surface-subtle--smbk-color-feedback-success-surface-subtlelight: #dffddfdark: #0a2d0echanges with themeColor
color.feedback.success.border-subtle--smbk-color-feedback-success-border-subtlelight: #8ddf90dark: #084712changes with themeColor
color.feedback.success.text-on-subtle--smbk-color-feedback-success-text-on-subtlelight: #016317dark: #8ddf90changes with themeColor
color.feedback.danger.surface-subtle--smbk-color-feedback-danger-surface-subtlelight: #fee5e1dark: #4b130echanges with themeColor
color.feedback.danger.border-subtle--smbk-color-feedback-danger-border-subtlelight: #febdb2dark: #761812changes with themeColor
color.feedback.danger.text-on-subtle--smbk-color-feedback-danger-text-on-subtlelight: #a51d17dark: #febdb2changes with themeColor
color.feedback.warning.surface-subtle--smbk-color-feedback-warning-surface-subtlelight: #ffe6dbdark: #431b07changes with themeColor
color.feedback.warning.border-subtle--smbk-color-feedback-warning-border-subtlelight: #febea2dark: #692903changes with themeColor
color.feedback.warning.text-on-subtle--smbk-color-feedback-warning-text-on-subtlelight: #913900dark: #febea2changes with themeColor
focus.ring.offset--smbk-focus-ring-offset2pxFocus
color.surface.hover--smbk-color-surface-hoverlight: #373d4326dark: #606a754dchanges with themeColor
color.feedback.info.border--smbk-color-feedback-info-border#557bffColor
color.feedback.success.border--smbk-color-feedback-success-border#269936Color
color.feedback.danger.border--smbk-color-feedback-danger-border#f34336Color
color.feedback.warning.border--smbk-color-feedback-warning-border#da601aColor
color.action.brand.background-hover--smbk-color-action-brand-background-hover#a51d17Color
color.action.brand.border-hover--smbk-color-action-brand-border-hover#0000000dColor
color.action.outline.background-hover--smbk-color-action-outline-background-hoverlight: #373d431adark: #606a751achanges with themeColor
color.action.outline.border-hover--smbk-color-action-outline-border-hoverlight: #9ba5b1dark: #4e555echanges with themeColor
color.action.default.background-pressed--smbk-color-action-default-background-pressedlight: #c4cdd8dark: #4e555echanges with themeColor
elevation.inset-strong--smbk-elevation-inset-stronglight: inset -1px 2px 2px 0px #373d4333dark: inset -1px 2px 2px 0px #0000004dElevation
color.action.brand.background-pressed--smbk-color-action-brand-background-pressed#761812Color
color.action.outline.background-pressed--smbk-color-action-outline-background-pressedlight: #c4cdd8dark: #2d3237changes with themeColor
Manifest
tag.manifest.json
{
  "name": "tag",
  "block": "smbk-tag",
  "summary": "A small label naming a category, with an optional leading icon or picture and remove control; pressable, it opens something about what it names.",
  "adapt": "css",
  "axes": {
    "tone": {
      "values": [
        "default",
        "brand",
        "outline",
        "info",
        "success",
        "danger",
        "warning"
      ],
      "default": "default",
      "description": "A see-through gray that shows on every surface, brand, outlined, or one of the four feedback families on their subtle surfaces."
    }
  },
  "flags": {
    "pressable": {
      "description": "The tag is a button that opens something about what it names, such as a card, with the hover, pressed and focus looks in the tag's own shape. The wrapper sets it when given onClick, as a popover's opener is; plain markup sets it on a button."
    }
  },
  "parts": [
    "icon",
    "leading-content",
    "label",
    "remove"
  ],
  "figmaNodeId": "4088:12242"
}