Tag
A tag labels something with a category. It can also be removed, selected, or followed as a link. Some systems call it a chip.
<tk-tag color="purple">Research</tk-tag> <tk-tag color="teal">Hiking</tk-tag> <tk-tag color="blue">Design</tk-tag>
Anatomy
| Part | What it is |
|---|---|
tk-tag |
the pill, 24px tall |
| default slot | the label, 1 to 3 words; it names everything the tag does |
leading slot |
an optional icon or avatar, hidden from screen readers |
| remove button | the ✕ of a removable tag |
| state mark | the + or ✓ of a selectable tag |
Kinds
<tk-tag color="blue">Static</tk-tag> <tk-tag color="blue" removable>Status: open</tk-tag> <tk-tag color="teal" selectable selected>Hiking</tk-tag> <tk-tag color="pink" href="/tags/design">design</tk-tag>
Give each tag one job. If you set more than one kind, removable wins over selectable,
and selectable wins over href.
- Static (default): a label. It takes no focus.
removable: a ✕ button that firestk-remove. The tag doesn't remove itself: your handler removes it and moves focus.selectable: the whole tag is a toggle that shows + when off and ✓ when on. Use it for filter bars and pick lists. It fireschangewhen the user toggles it, not when your code setsselected.href: the whole tag is a link with an underlined label. Use it where tags are usually links, such as "all posts with this tag", not for main navigation.target="_blank"addsrel="noreferrer noopener".
Colors
<tk-tag color="red">Red</tk-tag> <tk-tag color="orange">Orange</tk-tag> <tk-tag color="green">Green</tk-tag> <tk-tag color="indigo">Indigo</tk-tag> <tk-tag>Gray</tk-tag>
color takes 13 names: red, orange, yellow, green, mint, teal, cyan,
blue, indigo, purple, pink, brown, and gray (default).
- Use one color per category, the same everywhere it appears.
- Give neighboring categories different colors.
- Use
grayfor people and for labels with no category.
Colors for labels people create
To color tags people type, hash the label onto the 12 colors other than gray. The same label always gets the same color; two labels can share one. Trim and lowercase typed labels before hashing.
const CHROMATIC = ['red', 'orange', 'yellow', 'green', 'mint', 'teal',
'cyan', 'blue', 'indigo', 'purple', 'pink', 'brown'];
function tagColor(label) {
let h = 5381;
for (const ch of label) h = ((h * 33) ^ ch.codePointAt(0)) >>> 0;
return CHROMATIC[h % 12];
}Leading icon or avatar
<tk-tag color="green"><tk-icon slot="leading" name="star"></tk-icon>Featured</tk-tag> <tk-tag removable><tk-avatar slot="leading" shape="circle" size="20" name="Mira Petrova"></tk-avatar>Mira Petrova</tk-tag>
- An icon is drawn at 16px in the tag's color.
- A person is a size-20
tk-avatarinleadingwith the name as the label. TheAvatar shape rule applies: a circle for people, a square for teams and organizations. - Always write the name. Don't add a presence dot; there is no room.
- Keep people tags
grayunless the color means a category.
Long labels and groups
- A label never wraps. Limit the tag's width and the label ends in an ellipsis; the ✕ or ✓ stays. Screen readers still hear the full label.
- Keep labels under about 20 characters. Show the full text in a
Tooltip . - Tags flow and wrap like words. Keep one kind per group.
- Too many tags? Show the first few and add a "+N" tag named "N more tags". The group is yours to build.
When to use
- Use a tag for a category: a keyword on a card, a category in a table cell, a filter in a toolbar, a recipient in a share dialog.
- Use a
Badge for a status or a count. A red tag is a category, never an error. - Use a
Radio group for one choice in a form, and aSegmented control to switch views. - Use a
Button or aMenu for an action. A clickable tag is a link.
Content
- Write 1 to 3 words, in sentence case, with no end punctuation.
- Keep the meaning in the words. Color only helps tell tags apart.
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Give neighboring categories different colors | Use one color for different categories side by side |
| Keep one color per category everywhere | Recolor the same tag in another view |
| Give each tag one job | Make one tag both removable and a link |
| Use a Badge for status and counts | Make a status look like a colored tag |
| Name the ✕ after the label: "Remove Bug" | Name every ✕ "Clear filter" |
| Write the name next to the avatar in a person tag | Show a person by avatar alone |
| Keep one kind per group | Mix selectable and removable tags in a row |
| Truncate long labels and show them in a Tooltip | Let a tag wrap onto two lines |
Related
Badge : status and counts; never interactive.Avatar : the face in a person tag.Tooltip : the full text of a truncated tag.Multiselect : picks several options and shows them as tags.
API
Attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
color |
one of 13 color names | gray |
the category color |
removable |
boolean | false |
adds the ✕ button; wins over selectable and href |
remove-label |
string | Remove {label} |
the ✕ button's name |
selectable |
boolean | false |
makes the tag a toggle; wins over href |
selected |
boolean | false |
the toggle's state |
href |
string | makes the tag a link | |
target |
string | the link target; _blank adds rel="noreferrer noopener" |
Slots
| Slot | Content |
|---|---|
| default | the label |
leading |
a tk-icon or a size-20 tk-avatar |
Events
| Event | Fires when |
|---|---|
tk-remove |
the ✕ is activated; not cancelable. Remove the tag in your handler |
change |
the user toggles a selectable tag; read selected |
tk-tag.focus() focuses the tag's button or link.
Tokens
| Element | Tokens |
|---|---|
| fill | categorical/{color}/surface |
| label, icon, ✕, + and ✓ | categorical/{color}/text |
| border of interactive kinds | categorical/{color}/border |
| shape | radius-full |
| label type | font-size-xs, font-weight-medium, letter-spacing-caption |
| icons | icon-size-16 leading, icon-size-12 for ✕, + and ✓ |
| spacing | space-4, space-8 |
| focus ring | border/accent/focus |
Values per theme:
Accessibility
Built in:
- The ✕ button is named "Remove {label}" from the label.
- A selectable tag is a toggle button with
aria-pressed. A clickable tag is a link named by its label. - Each interactive tag is one Tab stop. A static tag is skipped.
- The leading icon or avatar is hidden from screen readers.
- Labels are at least 4.5:1 in every theme, also on hover and press.
Your part:
-
After removing a tag, move focus to the previous tag, or to the field or heading the group belongs to when none are left:
group.addEventListener('tk-remove', (e) => { const tag = e.target; const prev = tag.previousElementSibling; tag.remove(); (prev ?? group.querySelector('tk-tag') ?? anchor).focus(); }); -
Set
remove-labelwhen the label alone isn't clear: "Remove filter: Status is open". -
Translate
remove-labelfor other languages.
| Key | Action |
|---|---|
Tab |
moves to the next ✕, toggle, or link |
Enter / Space |
removes, toggles, or follows; a link opens with Enter |
Contrast limits
- The tinted border of interactive tags is under 3:1 in light, so it doesn't mark them as interactive. The ✕, + and ✓ marks and the link underline do.