Palette Tools & Generator Workflow
Master modern palette tools and generator workflows — from OKLCH-based algorithmic scales to token-ready export pipelines that keep design and code in sync.
9 min read
The full lesson
Palette generators have grown up. They are no longer simple color-wheel toys. Today they produce perceptually uniform scales, enforce contrast requirements, and output token-ready JSON.
Knowing the right tools — and how to connect them — is what separates a designer who ships a single brand color from one who ships a living, scalable color system.
This lesson walks through the full generator workflow: picking the right tool for each phase, building in OKLCH instead of legacy HSL, validating against WCAG 2.2 AA contrast, and wiring everything into a three-tier token architecture that stays in sync across Figma, code, and documentation.
Why Legacy Tools Fall Short
For years, the standard approach was simple: pick a hex value, run it through Adobe Color or Coolors, save the five-swatch result as a PNG, and manually type hex codes into Figma. That workflow has three compounding problems.
Perceptual unevenness. HSL “lightness” is not the same as how your eye perceives lightness. A 50% HSL yellow and a 50% HSL blue look very different in real brightness. Tonal scales built in HSL skip and clump visually — step 400 and step 500 may look nearly identical, while step 700 and step 800 feel miles apart. Tools that work in OKLCH or CIELAB avoid this because their lightness axis actually tracks human vision.
No contrast guarantee. Generating a palette is only half the job. Without contrast validation built into your workflow, you discover failures late — often in QA or, worse, a legal accessibility audit. Tools that keep generation and validation separate create a dangerous gap.
No token output. A palette that lives only in a PNG or Figma fill style cannot be consumed by code without manual transcription. And manual transcription drifts over time. A modern workflow ends with machine-readable token output — a format that code, Figma, and documentation all read from a single source of truth.
The Modern Tool Landscape
No single tool covers every phase. Think of your toolkit as three layers.
Generative / Exploration Tools
These tools help you discover palette candidates. Use them early and quickly — they are not the source of truth.
- Coolors — fast, keyboard-driven hue exploration. Good for early mood and hue-direction decisions. Output is flat hex, so treat it as raw material, not finished tokens.
- Huemint — ML-assisted palette generation that proposes multi-role palettes (background, text, accent) all at once. Useful for checking that your generated hues work as a system before you commit.
- Realtime Colors — previews palettes inside a live UI mock. This closes the gap between “the palette looks good in isolation” and “the palette works in context.”
- UI Colors (uicolors.app) — generates a ten-step tonal scale from a single seed color using an OKLCH interpolation model. Outputs Tailwind-compatible scales, HSL variables, and raw OKLCH values.
Precision / Scale-Building Tools
Once you have a hue direction, these tools produce the actual tonal scale you ship.
- Huetone — arguably the best open-source tool for OKLCH-based scale building. You set a lightness curve, a chroma curve, and a hue offset per step. It shows a real-time WCAG contrast readout for every step pairing. Export as CSS custom properties, JSON, or Tailwind config.
- Palette by Eigenvector — similar to Huetone, but adds a “target contrast” mode. You specify the contrast ratio you need for a given step and the tool solves for the OKLCH lightness value that hits it.
- Colorbox by Lyft — older but still useful for understanding how lightness curves map to perceived contrast. Good for learning; Huetone has largely replaced it for production work.
- Radix Colors — not a generator, but a reference implementation. The Radix twelve-step semantic scale (steps 1–12 with documented roles) is an excellent model to clone when building your own system.
Validation Tools
Validation should happen throughout generation, not only at the end.
- Colour Contrast Analyser (TPGi) — a desktop app that checks WCAG 2.2 AA and AAA for both regular and large text in a single click. Indispensable for spot-checking specific values.
- Leonardo (Adobe) — generates scales by targeting specific contrast ratios against a chosen background. You declare “I need a step that hits 4.5:1 on white” and Leonardo solves backward. This inverts the usual workflow in a very useful way.
- Polypane — a browser devtool that shows per-element contrast ratios live as you build. It cuts the test-fix loop during implementation.
- Figma’s built-in contrast checker — available in the inspect panel since 2023. Convenient, but it only checks selected layers and does not scan a whole file for failures.
Building a Tonal Scale in Practice
A production tonal scale typically has 10–12 steps. Material, Radix, and Tailwind each use slightly different conventions, but the logic is the same: steps near 0 are near-white, steps near 1000 (or 12 in Radix’s system) are near-black, and the middle steps carry your brand hue at full saturation.
A workflow using Huetone looks like this:
- Set base hue and chroma. Enter your brand hex or OKLCH value. Huetone locks the hue and chroma at the center of the scale and interpolates outward.
- Adjust the lightness curve. The default linear curve usually clusters steps near the light end. Pull the curve to distribute perceived lightness evenly — this is what makes the scale feel regular.
- Check contrast pairs. For each semantic role (surface, on-surface, border, interactive, disabled), verify that the intended step pairings hit 4.5:1 for normal text and 3:1 for large text and UI components.
- Name steps consistently. Use a numeric convention: 50, 100, 200 … 900, 950 (Tailwind-style) or 1–12 (Radix-style). Never name steps “light”, “dark”, or “medium” — those names are relative and break the moment you add a dark mode.
- Export. Export as JSON or CSS custom properties. These exported values become your primitive tokens.
{
"color": {
"brand": {
"50": { "$value": "oklch(97% 0.02 265)", "$type": "color" },
"100": { "$value": "oklch(93% 0.05 265)", "$type": "color" },
"200": { "$value": "oklch(86% 0.09 265)", "$type": "color" },
"300": { "$value": "oklch(76% 0.13 265)", "$type": "color" },
"400": { "$value": "oklch(65% 0.17 265)", "$type": "color" },
"500": { "$value": "oklch(54% 0.20 265)", "$type": "color" },
"600": { "$value": "oklch(44% 0.18 265)", "$type": "color" },
"700": { "$value": "oklch(35% 0.15 265)", "$type": "color" },
"800": { "$value": "oklch(26% 0.11 265)", "$type": "color" },
"900": { "$value": "oklch(17% 0.07 265)", "$type": "color" },
"950": { "$value": "oklch(11% 0.04 265)", "$type": "color" }
}
}
}
The W3C Design Token Community Group (DTCG) stable format uses $value and $type keys. Any token toolchain that follows this spec — Style Dictionary 4, Tokens Studio, Cobalt — can parse this directly.
Wiring Tokens Into Your Three-Tier Architecture
The palette scale is only the first tier. Shipping it straight into components creates the “blue-500 everywhere” anti-pattern — and that makes theme changes a find-and-replace nightmare.
The three tiers are:
| Tier | Example name | Example value | What it maps to |
|---|---|---|---|
| Primitive | color.brand.500 | oklch(54% 0.20 265) | Raw scale step |
| Semantic | color.action.default | {color.brand.500} | Role in the UI |
| Component | button.bg.default | {color.action.default} | Specific component slot |
Semantic tokens reference primitives by alias — that is the {...} syntax in DTCG. When you introduce dark mode, you override only the semantic layer. For example, color.action.default resolves to color.brand.300 instead of color.brand.500 on dark backgrounds. You never touch any component token or any component code.
This is what makes the generator workflow matter beyond aesthetics. A palette built in a tool and exported as raw hex values is just a bag of colors. A palette exported as DTCG-format primitives, wrapped in semantic aliases, and synchronized to Figma via a plugin like Tokens Studio or Variables is a living system.
Figma Integration
Since Figma introduced Variables (2023) and the stable Variables API, the palette-to-Figma pipeline has become clean and straightforward.
Tokens Studio for Figma is the most mature plugin for this flow. It reads a DTCG-format JSON file from a GitHub repo, creates Figma Variables for every token, resolves aliases, and syncs bidirectionally. Changes made in Figma can be pushed back to the JSON source.
Figma’s native Variables can now store color, number, string, and boolean values with mode overrides (light/dark). For smaller teams that do not need a full token pipeline, authoring variables natively and exporting via the Variables REST API is a viable path.
The handoff model has changed. Instead of a designer exporting a Zeplin redline PDF with hex values, the developer consumes token names. Dev Mode in Figma surfaces variable names alongside rendered values. Code Connect can link a Figma component directly to its Storybook story, so the token names a developer sees in Figma match the prop names in the component library.
Do
Don't
Automating Contrast Validation in CI
Manual spot-checking in a desktop tool is not enough for a team that ships continuously. You can automate contrast validation.
- Style Dictionary transforms your DTCG token JSON into platform outputs (CSS, iOS Swift, Android XML). Custom actions can check every semantic token pairing against WCAG 4.5:1 at build time and fail the pipeline if a pair regresses.
- Storybook’s a11y addon (powered by axe-core) runs WCAG contrast checks on every story on every CI run. A PR that introduces a contrast failure blocks the merge.
- Playwright / Cypress with axe-core extends the same checks to fully rendered pages.
The pattern to adopt: primitive tokens are “unsafe” — they carry no contrast guarantee, they are just scale steps. Semantic tokens are “safe” — verified at generation time that the foreground/background pair hits the required ratio. Components reference only semantic tokens. This makes the guarantee structural, not procedural — the system enforces it, not individual developers checking manually.
Outdated Habits to Retire
A few practices are still common in 2026, and they actively harm color systems.
Building in HSL. Using HSL darken/lighten functions (or the old Sass equivalents) produces uneven scales and unexpected hue shifts. OKLCH is the right color space for palette work. It is supported natively in CSS and in every major generator tool.
Naming tokens by value. A token named color.blue-500 breaks the moment the brand refreshes to teal. Role-based names like color.interactive.default survive a rebrand.
Flat palette files per platform. Maintaining a separate colors.swift, colors.xml, and colors.css with hardcoded values means three files drift out of sync within weeks. A single DTCG JSON source with platform transforms in Style Dictionary eliminates the drift.
Using pure black for dark backgrounds. #000000 and #FFFFFF at full contrast create halation (a visual glow effect) and eye fatigue. Dark mode surfaces should start near #0A0A0A to #121212 for backgrounds and #F2F2F2 for primary text. This is not a matter of preference — it matches how display panels render color and reduces the perceptual glow effect on OLED screens.
Choosing the Right Tool for Each Phase
| Phase | Best tool(s) | Output |
|---|---|---|
| Hue exploration | Coolors, Realtime Colors, Huemint | Candidate hue directions |
| Scale construction | Huetone, UI Colors, Leonardo | Tonal scale in OKLCH |
| Contrast validation | Leonardo, Colour Contrast Analyser, Polypane | Verified step pairings |
| Token authoring | DTCG JSON (hand-authored or Tokens Studio) | Primitive + semantic tokens |
| Figma sync | Tokens Studio, Figma Variables API | Variables in Figma |
| Platform output | Style Dictionary 4 | CSS, Swift, XML, etc. |
| CI validation | axe-core, Storybook a11y addon | Automated contrast gate |
No single tool handles all seven phases well. Resist the urge to stay inside one ecosystem. The cost of combining Tokens Studio for authoring with Style Dictionary for output is low. The benefit — best-in-class tooling at every phase — is high.