Skip to main content

Badge

A short label for a status, category or count, next to what it describes.

In Brand expressive

See it live​

Start Storybook to see it live: npm run storybook

When to use it​

In Brand expressive: New and limited labels.

  • Use it when: A state people scan for in a list or table, or a small category label.
  • Not when: A message people must read (alert or toast), or an action (a button).

Instead:

  • Alert: A message, not a label.
  • Button: Something to press.

Variants​

What each variant is for in any design system, then what Brand expressive decided and why. Each sample is the live story with that variant set.

neutraltoneUsed in Brand expressive
Start Storybook to see it live

What it is for

A label with no status meaning: a category, a count, a waiting state.

✓Nothing is wrong and nothing needs doing.
✕The state needs attention.

In Brand expressive

New: a label, not a state to fix.

infotoneNot used in Brand expressive
Start Storybook to see it live

What it is for

News: worth knowing, nothing to act on.

✓Something is happening or coming.
✕Something is wrong or nearly wrong.

In Brand expressive

Campaign labels are a state or a nudge; there are no plain news labels.

successtoneUsed in Brand expressive
Start Storybook to see it live

What it is for

Done, healthy or paid.

✓The outcome people wanted.
✕A state that is only waiting.

In Brand expressive

On the list: you joined and your place is saved.

warningtoneUsed in Brand expressive
Start Storybook to see it live

What it is for

Needs attention soon; nothing has failed yet.

✓A risk people can still act on.
✕Something already failed.

In Brand expressive

Almost gone: few left, act soon.

dangertoneNot used in Brand expressive
Start Storybook to see it live

What it is for

Failed, blocked or lost; act now.

✓A real failure or loss.
✕Anything that is only unusual.

In Brand expressive

Nothing on a launch page is labeled as failed; errors are plain sentences.

How Brand expressive uses it​

A status
Use Badge pill with a word
Not Color alone
A word keeps meaning on vivid backgrounds.
Shape of a status badge
Use radius.badge (pill)
Not A rectangle
Pills match the controls.

Why it works this way​

Badge looks the way it does because of 4 answers about this product. Each card is one answer, in three steps: the answer, what it decided for Badge, and what would move if it changed.

How many signals carry each meaning?accessibility.count
1The answer
Two: color and word

Color and word.

2So Badge
  • ✓uses neutral: New: a label, not a state to fix.
  • ✓uses success: On the list: you joined and your place is saved.
  • ✓uses warning: Almost gone: few left, act soon.
It also shapes Alert: destructive
3If it changed
3
Badge decisions would reopen

No other answer follows from it.

What is the main content?content.q1
1The answer
Images and campaigns

Images, campaigns and short punchy copy.

2So Badge
  • –does not use info: Campaign labels are a state or a nudge; there are no plain news labels.
It also shapes Empty: default Input group: block-start Input group: block-end
3If it changed
1
Badge decision would reopen

and 10 answers that follow from it: One idea at a time, Browse and explore, Regular, and 7 more.

Which outcome matters most?outcomes.q1
1The answer
Engagement

Engagement and sign-ups.

2So Badge
  • ✓uses warning: Almost gone: few left, act soon.
It also shapes Button: primary Button: large Toast: success Toggle: lg
3If it changed
1
Badge decision would reopen

and 6 answers that follow from it: A few minutes, Brand moments, Hero and launch moments, and 3 more.

How many tones does it use?voice.count
1The answer
One per moment

Playful in headlines, plain in errors.

2So Badge
  • –does not use danger: Nothing on a launch page is labeled as failed; errors are plain sentences.
It also shapes Toast: neutral Toast: danger Alert: default Alert: destructive
3If it changed
1
Badge decision would reopen

No other answer follows from it.

Words​

  • Headlines are short and bold. Three to six words.
  • Verbs that move: Join, Try, Go.
  • Playful in headlines, plain in errors.
  • Use: Join, Drop, Go, Love. Avoid: Synergy, Leverage, Kindly.

The labels components use, from the voice tokens:

  • content.action.commit: Go
  • content.action.cancel: Not now
  • content.action.destroy: Remove
  • content.action.retry: Try again
  • content.action.empty-action: Explore the drop

See Voice and tone for the whole voice.

Accessibility and keyboard​

Test before you ship:

  • The status is a word; color and icon add to it, never replace it. undefined

Use it in code​

npx open-ds add badge

The component reads only component keys and semantic tokens, so it follows the brand and mode on <html>.

Tokens it reads​

Badge reads 17 tokens of its own, each an alias of a semantic token. Each row is one part: its own token, the semantic it aliases, and the value it ends at. Change a semantic and every component that reads it follows; override one of Badge's tokens to change Badge alone.

Changes with theme

Brand expressive decides what changes when you switch theme. Here a switch changes colors only, so the marked rows differ between light and dark; everything else holds steady.

PartIts token and the semantic it aliasesValue
Badge
Cornercomponent.badge.radiusradius.badgevar(--badge-radius)radius.999:9999px
Padding, left and rightcomponent.badge.padding-xspace.gap.tightvar(--badge-padding-x)space.8:0.5rem
Text sizecomponent.badge.font-sizetype.caption.font-sizevar(--badge-font-size)font.size.14:0.875rem
Gapcomponent.badge.gapspace.gap.tightvar(--badge-gap)space.8:0.5rem
Padding, top and bottomcomponent.badge.padding-ycomponent-spacing-map.hairlinevar(--badge-padding-y)space.2:0.125rem
Weightcomponent.badge.font-weighttype.label.font-weightvar(--badge-font-weight)font.weight.700:700
Font familycomponent.badge.font-familytype.caption.font-familyvar(--badge-font-family)font.family.dm-sans:"DM Sans", system-ui, sans-serif
Neutral
Fill
Changes with theme
component.badge.neutral.backgroundcolor.surface.sunkenvar(--badge-neutral-background)Lighttaupe.light.100:#FCEFE6Darktaupe.dark.100:#33241F
Text
Changes with theme
component.badge.neutral.labelcolor.text.secondaryvar(--badge-neutral-label)Lighttaupe.light.700:#4D3A33Darktaupe.dark.500:#E2C4B3
Success
Fill
Changes with theme
component.badge.success.backgroundcolor.status.success.subtlevar(--badge-success-background)Lightgreen.light.100:#DBF7DFDarkgreen.dark.100:#013118
Textcomponent.badge.success.labelcolor.text.success-on-lightvar(--badge-success-label)green.light.800:#023E17
Warning
Fill
Changes with theme
component.badge.warning.backgroundcolor.status.warning.subtlevar(--badge-warning-background)Lightamber.light.100:#FEE8CFDarkamber.dark.100:#3B2701
Textcomponent.badge.warning.labelcolor.text.warning-on-lightvar(--badge-warning-label)amber.light.800:#462A02
Danger
Fill
Changes with theme
component.badge.danger.backgroundcolor.status.danger.subtlevar(--badge-danger-background)Lightred.light.100:#FFDBD8Darkred.dark.100:#481316
Textcomponent.badge.danger.labelcolor.text.danger-on-lightvar(--badge-danger-label)red.light.800:#6D0008
Info
Fill
Changes with theme
component.badge.info.backgroundcolor.status.info.subtlevar(--badge-info-background)Lightblue.light.100:#D3E4FFDarkblue.dark.100:#13284B
Textcomponent.badge.info.labelcolor.text.info-on-lightvar(--badge-info-label)blue.light.800:#001A4E