Token
Pill that names a design token or another short machine value (color-accent, spacing-md). Soft hue pair, pink by default, so it reads as a value and not a status. One optional leading element: a 12px icon, a 12px swatch that shows a color token in the active mode, or a 16px Avatar for a person or team. With onRemove it ends in a remove button, for picked values the user can take out.
Preview
import { Token } from "@/components/ui/token"
<Token>spacing-md</Token>Usage
When to use
- Show a design token name or another short machine value, in tables or inside running text.
- Show the color of a color token with a swatch next to its name.
- Show values the user picked and can take out again, such as active filters, with onRemove.
When not to use
- Status or categories. Use Badge.
- As a button or link on its own. To make a token copyable, wrap it in a button and give the button the label.
Variants
color
Soft pair: background-<hue> with text-<hue>. Never the solid. pink is the default so tokens stand apart from status badges.
import { Token } from "@/components/ui/token"
<Token>spacing-md</Token>
<Token color="red">spacing-md</Token>
<Token color="orange">spacing-md</Token>
<Token color="yellow">spacing-md</Token>
<Token color="green">spacing-md</Token>
<Token color="teal">spacing-md</Token>
<Token color="blue">spacing-md</Token>
<Token color="purple">spacing-md</Token>
<Token color="gray">spacing-md</Token>Examples
Default
import { Token } from "@/components/ui/token"
<Token>spacing-md</Token>Color token
The swatch reads the token, so it changes with the mode.
import { Token } from "@/components/ui/token"
<Token swatch="var(--color-accent)">color-accent</Token>With icon
import { IconRuler } from "@tabler/icons-react"
import { Token } from "@/components/ui/token"
<Token>
<IconRuler size={12} />
size-element-md
</Token>Removable
A picked value the user can take out. removeLabel names the button with the value.
import { Token } from "@/components/ui/token"
<Token color="blue" onRemove={removeToken} removeLabel="Remove font-size-md">font-size-md</Token>With avatar
A recipient the user picked. The token names the person, so the avatar's alt is empty.
import { Avatar } from "@/components/ui/avatar"
import { Token } from "@/components/ui/token"
<Token color="gray" avatar={<Avatar variant="solid" color="blue" alt="">A</Avatar>} onRemove={removeToken} removeLabel="Remove ada@example.com">ada@example.com</Token>Do and don't
Do
- Use it wherever docs or UI show a token name, in tables and inside running text.
- Add a swatch for color tokens, pointing at the token itself: swatch="var(--color-accent)".
- Keep the label exactly as it is written in code.
- Give a removable token a removeLabel with its value: Remove spacing-md.
- For a value that is a person or a team, lead with a solid Avatar and one initial.
Don't
- Don't use it for status or categories; that is Badge.
- Don't put more than one leading element (icon, swatch or avatar) in the same token.
- Don't use it as a button or link on its own.
- Don't make a token removable when the user can't add it back; removing must be something they can undo.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| color | enum | pink | red | orange | yellow | green | teal | blue | purple | gray | pink | Soft pair: background-<hue> with text-<hue>. Never the solid. pink is the default so tokens stand apart from status badges. |
| swatch | string | - | - | CSS color for the leading swatch, usually var(--color-<token>) so it follows light and dark. Leave it out for tokens that are not colors. |
| avatar | node | - | - | A solid Avatar before the label, for a value that is a person or a team, such as a recipient: <Avatar variant="solid" color="blue" alt="">A</Avatar>. One initial; the token sets its size. |
| onRemove | function | - | - | Called when the remove button is pressed. Setting it shows the button. Use for values the user picked and can take out again, such as filters or the values of a multi-value field. |
| removeLabel | string | - | - | Accessible name of the remove button, with the value in it: Remove spacing-md. Required with onRemove. |
Slots
| Name | Required | Description |
|---|---|---|
| label | yes | The token name or value, as written in code. |
| icon | no | Optional leading icon. Use either an icon or a swatch, not both. |
Anatomy
| Part | Description |
|---|---|
| root | The pill: soft hue fill, radius-full, compact type, 20px tall. Text in a paragraph with a Token uses leading-5. |
| icon | Optional Tabler icon before the label, 12px. |
| swatch | Optional 12px circle filled with the token color, with a border-strong edge. |
| avatar | Optional Avatar before the label, drawn at 16px with 12px initials and pulled into the pill's padding, so the token stays 20px tall. Solid, since the soft fill would not stand out on the pill. |
| remove | Optional remove button at the end: a 16px circle around a 12px X in the token's hue. Neutral hover and pressed overlays, focus ring. |
| hitArea | Transparent ::before centered on the remove button, never smaller than size-target-min (24px on mouse, 44px on touch). |
Accessibility
Role: generic
| Keys | Action |
|---|---|
| Tab | With onRemove: moves focus to the remove button and shows the focus ring. |
| Enter, Space | With onRemove: removes the token. |
- Token itself is not interactive. To make a token copyable, wrap it in a button and give the button the label.
- The remove button is a real button named by removeLabel, which must include the value (Remove spacing-md), since a page often holds several. The type requires removeLabel with onRemove.
- After a remove, move focus to the next token's remove button or back to the field the tokens belong to, so focus is not lost with the button.
- The remove button is 16px but its hit area is size-target-min (24px on mouse, 44px on touch).
- The leading avatar is hidden from screen readers (aria-hidden), since the label names the person.
- The swatch and icon are decorative (aria-hidden). The text is the token name, so the meaning never depends on color.
- Text stays selectable, so a reader can copy the token name.
Install
npx shadcn add https://werewolf-ui.vercel.app/r/token.jsonThis also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").