Badge
A short label for a status, category or count, next to what it describes.
In Multi-brand
See it live
npm run storybookWhen to use it
In Multi-brand: Plan and status 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:
Variants
What each variant is for in any design system, then what Multi-brand decided and why. Each sample is the live story with that variant set.
neutraltoneUsed in Multi-brandWhat it is for
A label with no status meaning: a category, a count, a waiting state.
In Multi-brand
Trial: the plan works and billing has not started.
infotoneUsed in Multi-brandWhat it is for
News: worth knowing, nothing to act on.
In Multi-brand
Renews in 3 days: a payment is coming; nothing has gone wrong.
successtoneUsed in Multi-brandWhat it is for
Done, healthy or paid.
In Multi-brand
Active: the plan is paid and running.
warningtoneNot used in Multi-brandWhat it is for
Needs attention soon; nothing has failed yet.
In Multi-brand
No plan or order state sits between running and failed; a coming renewal is news, not a warning.
dangertoneUsed in Multi-brandWhat it is for
Failed, blocked or lost; act now.
In Multi-brand
Card declined: the payment failed, so the plan will stop.
How Multi-brand uses it
Why it works this way
Badge looks the way it does because of 3 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.
accessibility.count1The answer
Brand colors vary, so meaning needs a word.
2So Badge
- ✓uses neutral: Trial: the plan works and billing has not started.
- ✓uses info: Renews in 3 days: a payment is coming; nothing has gone wrong.
- ✓uses success: Active: the plan is paid and running.
- –does not use warning: No plan or order state sits between running and failed; a coming renewal is news, not a warning.
- ✓uses danger: Card declined: the payment failed, so the plan will stop.
Alert: destructive3If it changed
No other answer follows from it.
content.q11The answer
Product pages, sign-up and account forms.
2So Badge
- –does not use warning: No plan or order state sits between running and failed; a coming renewal is news, not a warning.
Alert: default Input group: inline-start Input group: inline-end Input group: block-start Input group: block-end Item: outline3If it changed
and 9 answers that follow from it: A moderate amount, Gaps, insets and row heights, Comfortable, and 6 more.
outcomes.q21The answer
A page that looks like the wrong brand loses trust.
2So Badge
- ✓uses danger: Card declined: the payment failed, so the plan will stop.
Button: secondary Button: danger Alert: destructive3If it changed
and 1 answer that follow from it: Also for emphasis and size.
Words
- Shared structure: object, state, next step.
- Brand tone lives in headlines and marketing copy, not in errors.
- Errors and confirmations read the same in every brand.
- Use: Get started, Plan, Order. Avoid: Brand-specific words in errors, Jargon.
The labels components use, from the voice tokens:
content.action.commit: Savecontent.action.cancel: Cancelcontent.action.destroy: Removecontent.action.retry: Try againcontent.action.empty-action: Get started
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.
Multi-brand decides what changes when you switch theme. Here a switch changes colors, type and shape, so the marked rows differ between its brands and between light and dark; everything else holds steady.
| Part | Its token and the semantic it aliases | Value |
|---|---|---|
| Badge | ||
| Corner Changes with theme | component.badge.radiusradius.badgevar(--badge-radius) | Aster Lightradius.4:0.25remAster Darkradius.4:0.25remBirch Lightradius.999:9999pxBirch Darkradius.999:9999pxCoral Lightradius.999:9999pxCoral Darkradius.999:9999px |
| Padding, left and right | component.badge.padding-xspace.gap.tightvar(--badge-padding-x) | space.8:0.5rem |
| Text size | component.badge.font-sizetype.caption.font-sizevar(--badge-font-size) | font.size.13:0.8125rem |
| Gap | component.badge.gapspace.gap.tightvar(--badge-gap) | space.8:0.5rem |
| Padding, top and bottom | component.badge.padding-ycomponent-spacing-map.hairlinevar(--badge-padding-y) | space.2:0.125rem |
| Weight | component.badge.font-weighttype.label.font-weightvar(--badge-font-weight) | font.weight.600:600 |
| Font family Changes with theme | component.badge.font-familytype.caption.font-familyvar(--badge-font-family) | Aster Lightfont.family.inter:Inter, system-ui, sans-serifAster Darkfont.family.inter:Inter, system-ui, sans-serifBirch Lightfont.family.plus-jakarta-sans:"Plus Jakarta Sans", system-ui, sans-serifBirch Darkfont.family.plus-jakarta-sans:"Plus Jakarta Sans", system-ui, sans-serifCoral Lightfont.family.poppins:Poppins, system-ui, sans-serifCoral Darkfont.family.poppins:Poppins, system-ui, sans-serif |
| Neutral | ||
| Fill Changes with theme | component.badge.neutral.backgroundcolor.surface.sunkenvar(--badge-neutral-background) | Aster Lightslate-deep.light.100:#F1F5F9Aster Darkslate-deep.dark.100:#1E293BBirch Lightslate-deep.light.100:#F1F5F9Birch Darkslate-deep.dark.100:#1E293BCoral Lightslate-deep.light.100:#F1F5F9Coral Darkslate-deep.dark.100:#1E293B |
| Text Changes with theme | component.badge.neutral.labelcolor.text.secondaryvar(--badge-neutral-label) | Aster Lightslate-deep.light.700:#334155Aster Darkslate-deep.dark.500:#CBD5E1Birch Lightslate-deep.light.700:#334155Birch Darkslate-deep.dark.500:#CBD5E1Coral Lightslate-deep.light.700:#334155Coral Darkslate-deep.dark.500:#CBD5E1 |
| Success | ||
| Fill Changes with theme | component.badge.success.backgroundcolor.status.success.subtlevar(--badge-success-background) | Aster Lightgreen.light.100:#DBF7DFAster Darkgreen.dark.100:#012A14Birch Lightgreen.light.100:#DBF7DFBirch Darkgreen.dark.100:#012A14Coral Lightgreen.light.100:#DBF7DFCoral Darkgreen.dark.100:#012A14 |
| Text | component.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) | Aster Lightamber.light.100:#FEE8CFAster Darkamber.dark.100:#332201Birch Lightamber.light.100:#FEE8CFBirch Darkamber.dark.100:#332201Coral Lightamber.light.100:#FEE8CFCoral Darkamber.dark.100:#332201 |
| Text | component.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) | Aster Lightred.light.100:#FFDBD8Aster Darkred.dark.100:#410C11Birch Lightred.light.100:#FFDBD8Birch Darkred.dark.100:#410C11Coral Lightred.light.100:#FFDBD8Coral Darkred.dark.100:#410C11 |
| Text | component.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) | Aster Lightblue.light.100:#D3E4FFAster Darkblue.dark.100:#0D2244Birch Lightblue.light.100:#D3E4FFBirch Darkblue.dark.100:#0D2244Coral Lightblue.light.100:#D3E4FFCoral Darkblue.dark.100:#0D2244 |
| Text | component.badge.info.labelcolor.text.info-on-lightvar(--badge-info-label) | blue.light.800:#001A4E |