Why your badges look great in dark mode and washed out in light mode
Dark themes hide a badge's flaws. Here are the five rules we used to rebuild the Koala UI Badge for light and cream themes, with every example running live.
Short answer
Dark themes hide the problem: a light pastel on near-black glows on its own, so one color can serve as tint, text and fill. On white the same color gives a tint that barely shows and a border that reads as a smudge. Give every hue three roles per theme instead: a tone for tints and dots, an ink for text that darkens along the hue's own ramp, and a solid whose text passes WCAG AA.
In November 2026 we rebuilt the Koala UI Badge. Every version we tried looked good on near-black. Light mode was where it fell apart, and the cause was not one wrong value but one color doing too many jobs. These are the five rules we ended up with, and every example on this page is the shipping component.
The opacity trick, and why dark mode flatters it
Most soft badges are built the same way: one status color at 10% opacity for the fill, the same color at 25% for a hairline, and a darker version of it for the text. One token per hue, three jobs.
On a dark theme that works almost by accident. The hues are redefined lighter and calmer for dark surfaces, a light pastel on black glows on its own, and the text can simply be the tone. On white the same recipe gives a fill that barely shows and a border that looks like a smudge.
Rule 1: one color cannot do three jobs
A tint, a line of text and a solid fill need different lightness on white. So each hue now has three roles per theme: a tone for tints and dots, an ink for text on a tint, and a solid for fills that carry text.
On dark themes all three point at the same bright tone, which is why dark looked fine all along.
Rule 2: darken along the hue's own ramp
Mixing a color with black in OKLCH keeps its hue and lowers lightness. For green and blue that is close enough. Amber is where it breaks: a yellow hue taken dark turns olive. Real amber ramps turn toward orange as they darken, so the new amber ink moves its hue from 70 to 55.
The categorical hues had a quieter problem. Purple, pink, teal and orange used their tone as text, a mid-lightness color on its own tint. Each now has an ink of its own, a step darker.
/* light */
--success: oklch(0.723 0.219 149.6); /* tone: tints and dots */
--success-strong: oklch(0.5 0.14 150); /* ink: text on a tint */
--success-solid: oklch(0.53 0.15 150); /* solid: holds white text */
--warning-strong: oklch(0.5 0.13 55); /* amber turns orange as it darkens */
--purple-strong: oklch(0.45 0.2 310);
--pink-strong: oklch(0.47 0.19 350);
--teal-strong: oklch(0.42 0.1 192);
--orange-strong: oklch(0.48 0.15 45);
/* dark: every role is the bright tone */
--success-strong: var(--success);
--success-solid: var(--success);Rule 3: a border has to earn its place
If the fill already says the color, a hairline in the same bright hue adds a pale outline and nothing else. The default soft badge has no border now. When a badge needs an edge, on a busy card or a tinted surface, the surface appearance draws it in the ink at low opacity.
Rule 4: solid fills choose their text on purpose
A bright solid with white text is the most common contrast miss in badge sets. On light themes the green, sky and red solids step down until white text passes WCAG AA, and amber stays bright and takes dark text. On dark themes every solid is the bright tone and takes dark text.
You do not have to take our word for it. The table below measures every ink and every solid from the live tokens, right now, in your browser.
| Hue | On a tint | On a solid |
|---|---|---|
| success | … | … |
| warning | … | … |
| info | … | … |
| destructive | … | … |
| purple | … | … |
| pink | … | … |
| teal | … | … |
| orange | … | … |
| Measuring… | ||
Rule 5: separate the color from the shape
The old API mixed the two: one prop named the color and the treatment at once, so some pairs simply broke. Now variant is the tone and appearance is how it is painted, with soft as the default. A tone means the same thing in every appearance.
<Badge variant="success">Active</Badge>
<Badge variant="success" appearance="surface">Active</Badge>
<Badge variant="success" appearance="solid">Active</Badge>
<Badge variant="success" appearance="modern"><CheckCircle /> Ready</Badge>
<Badge variant="success" dot>Online</Badge>Bonus: motion that means something
A status badge is the one piece of UI that changes while people watch it: a deploy goes from queued to ready, a count goes up. So the badge got four animated parts, each tied to a real change.
Try it
The Badge docs have every appearance, the animated parts and their API, with the demo at the top of this post running live. For filters people toggle and clear, the Chip is its interactive sibling, with the same heights and tones.
About Koala UI
Koala UI is a React and Figma design system: accessible components, four themes, and source code you own.

Frequently asked questions
Why do soft badges look washed out in light mode?
Because one color is doing three jobs. A 10% tint of a bright hue over white is a pale pastel, a border in the same hue looks like a faint outline, and text darkened by mixing in black loses its color. On dark themes the hues are lighter and glow against the background, which hides all three problems.
How should I darken a color for badge text?
Darken it along its own ramp: lower the lightness in OKLCH and let the hue move where a real ramp moves it. Mixing with black keeps the hue, which is close enough for green and blue but turns amber olive, because real amber shifts toward orange as it darkens.
Should soft badges have a border?
Not by default. If the fill already carries the color, a hairline in the same bright hue adds noise. When a badge needs an edge, draw it in the darker ink at low opacity so it reads as an edge.
What contrast does badge text need?
Badge text is small, usually 12px, so it needs 4.5:1 against its fill to meet WCAG AA. That applies to the ink on a soft tint and to the text on a solid fill. Bright solids like green, sky and amber rarely reach 4.5:1 with white text, so step them down or give them dark text.
What is the difference between a badge and a chip?
A badge labels status, counts and categories. It can carry a remove button or act as a link, but it is not a control people toggle. A chip is interactive: people select it, toggle it or remove it, for example as a filter. In Koala UI they share heights and tones so they sit together cleanly.
Sources