How to Turn a Light Design System into a Dark Theme
In October 2026 HueWiz moved to a dark interface based on a light reference style: a warm cream canvas, near-black type and a single violet accent. Turning that into a dark theme took more than swapping black and white. Here is exactly how each design token was translated, with the contrast numbers, and the four problems we only caught once the redesign was live.
1. Inventory roles, not colors
Start by listing what each color does, not what it looks like. The light reference used six roles: a page canvas, a card surface one step lighter, a hairline border, primary text, secondary text and one violet action color. A dark theme has to fill the same roles. If you translate swatch by swatch instead, you end up with colors that look right in isolation and fail when they sit next to each other.
| Role | Light token | Dark token | Light contrast | Dark contrast |
|---|---|---|---|---|
| Page canvas | #F1F0EE | #121211 | — | — |
| Card surface | #FFFFFF | #1A1918 | — | — |
| Hairline border | #E4E2DF | #2E2D2A | — | — |
| Primary text | #161616 | #F1F0EE | 15.88:1 | 16.45:1 |
| Secondary text | #686868 | #A8A6A1 | 4.89:1 | 7.70:1 |
| Link / violet text | #6248FF | #9D8CFF | 4.73:1 | 6.80:1 |
Contrast is measured against each theme's page canvas with the WCAG 2 formula and truncated to two decimals.
2. Choose a base that keeps the temperature
The light canvas was a warm off-white (#F1F0EE), not pure white. We kept that warmth in the dark base, #121211, a near-black with a trace of the same yellow-brown hue. Pure #000000 was ruled out for two reasons. Bright text on true black can appear to smear or glow for some readers, especially on OLED screens. And a cool or neutral black would have quietly changed the brand's personality from warm to clinical.
3. Rebuild elevation: lighter means higher
In the light design, cards are white on a cream canvas and a soft shadow lifts them. On a dark canvas, shadows are almost invisible, so elevation has to come from lightness and borders. HueWiz uses three surface steps (canvas #121211, card #1A1918 and raised controls #22211F) plus a hairline border #2E2D2A. The rule we follow is that anything meant to separate from the base moves further from it in both themes. In the light theme borders are darker than the canvas; in the dark theme they are lighter. Translating the border's lightness directly would have made it darker than the canvas and invisible.
4. Keep the text hierarchy and check every surface
Primary text became #F1F0EE, the old canvas color, at 16.45:1 against the dark canvas. Secondary text is where most conversions go wrong. The light design's gray #686868 reached 4.89:1 on cream, just above the 4.5:1 AA minimum. In dark mode we gave secondary text more headroom: #A8A6A1 measures 7.70:1. Light text on dark backgrounds at the bare minimum tends to read thinner than the number suggests, particularly with lighter font weights.
We also added a third, quieter level for captions, #8A8883. It reaches 5.29:1 on the canvas but only 4.95:1 on a card. That is why every text token has to be checked against every surface it can appear on, not just the page background. The design token checker does this as a matrix.
5. One brand color, two tokens
The violet action color #6248FF works as a button fill in both themes: white text on it measures 5.39:1. As text on the dark canvas, though, the same violet measures only 3.47:1. That fails AA for normal text even though it passed on cream (4.73:1). The fix was to split the brand color into two tokens: #6248FF for fills and a lighter #9D8CFF for links and violet text (6.80:1). A paler lilac, #B8ADF5, handles labels and focus rings. Most brand accents need this split when they move to dark mode.
6. Use decoration sparingly, and lighten the dark end
The reference style used an orange-to-red-to-violet gradient on a single headline word. We kept the rule of one gradient word per page, but lightened the final violet stop to #8B76FF. Otherwise the end of the word sank into the dark background. Decorative color is the easiest thing to overuse in dark mode, because everything saturated looks brighter on black.
7. What broke in live testing
Static screenshots looked right. Testing the live site with real interactions found four problems.
- A global heading color overrode user content. We set every heading to the theme's text color. HueWiz's palette previews show your colors, and their headings are supposed to inherit the preview's text color. One "Make room for your next idea" heading turned nearly invisible on a light preview. Fix: theme the page chrome, never the content area that displays user colors.
- A sticky, transparent navigation bar. The new design removed the nav background, but the old layout kept it sticky, so page content scrolled visibly underneath it. Fix: the nav is no longer sticky.
- Cached stylesheets. The host served CSS with a seven-day cache, so a fix uploaded to the same URL did not reach browsers that already had the file. Fix: a version number in every stylesheet link, bumped whenever the theme changes.
- Browser-native controls. The file-upload button kept its bright default styling. Fix: style
::file-selector-buttonto match the theme.
Checklist for your own conversion
- List roles (canvas, card, border, text levels, action, link) before choosing colors.
- Pick a dark base that keeps the brand's temperature; avoid pure black.
- Make elevation lighter, and move borders away from the base in both themes.
- Check each text token against every surface it can sit on, not just the canvas.
- Split the accent into a fill token and a lighter text/link token.
- Keep user-content areas out of global theme rules.
- Version your stylesheet URLs before you ship.
Try it on your own palette: paste your tokens into the HueWiz design token checker to get a contrast matrix and a draft dark theme, or download HueWiz's dark tokens as a starting point.