OKLCH Theme Tokens
Define colour perceptually so a theme can shift without contrast collapsing somewhere.
What it adds
A colour foundation expressed as lightness, chroma, and hue values from which every theme in the app is derived.
What your agent is told to do
5
What your agent is told to do
5-
1
Find every colour the app currently defines as an opaque hex or RGB literal and re-express it as lightness, chroma, and hue, so that darkening a theme becomes a predictable adjustment rather than a fresh guess at a new hex value.
-
2
Hold the semantic roles constant while the underlying values move — danger must mean danger in every theme even when its lightness and hue differ. The role vocabulary itself belongs to Semantic Color Tokens; extend that set rather than inventing a parallel one here.
-
3
Emit a compiled fallback value beside every perceptual definition for the renderers that will not parse the newer syntax: email templates, PDF and print output, older embedded webviews, and any build tool in the pipeline that rewrites colour.
-
4
Record in the token source which values a person may edit and which are derived from them, so nobody hand-tunes a step that the next regeneration will silently overwrite.
-
5
Do not convert the existing palette mechanically and call it finished. A faithful one-to-one conversion preserves every contrast mistake the old palette had; check each foreground and background pair after conversion and correct the lightness where it was already failing.
Edge cases it handles
7
Edge cases it handles
7- Tooling that cannot parse the colour space will drop the declaration entirely and render the element unstyled or transparent, so every token needs a compiled fallback emitted alongside it rather than assumed.
- A chroma value that sits outside the display gamut will be clipped by the browser in ways that differ between devices — clamp it yourself to a defined in-gamut value so the same token does not render as two different colours on two screens.
- A semantic role must resolve to something in every theme. A token defined only for the light theme leaves a component with no colour at all in dark mode, which usually shows up as inherited black text on a near-black surface.
- Users and operators need to know which tokens are theirs to edit. An undocumented editable value gets changed, then reverted by a regeneration, and the report comes back as an intermittent bug.
- Interpolating between two perceptual colours in a gradient does not follow the same path as interpolating between their hex equivalents; check that existing gradients still pass through the intended midpoint.
- Rounding lightness to too few decimal places collapses adjacent steps of a ramp into the same rendered colour, which is only visible on large flat surfaces.
- A colour composited over another with alpha no longer has the lightness the token claims — measure the result, not the declaration.
Definition of done
8
Definition of done
8- Every colour in the shared token source is defined by lightness, chroma, and hue rather than by a literal hex value.
- Each perceptual definition ships with a compiled fallback that renders correctly in email, print, and older webviews.
- Out-of-gamut values are clamped to a defined in-gamut result rather than left to the browser to clip.
- Every semantic role resolves to a value in every theme, with no unresolved tokens.
- The token source states which values are user-editable and which are derived.
- Foreground and background pairs meet their contrast thresholds after conversion, including pairs that failed before it.
- The feature matches the existing design system.
- No existing functionality is broken.
Related features
Z-Index Registry
Z-Index Registry
Keep every stacking value in one file so nobody has to guess a bigger number.
What it does
A single source of named z-index tokens, with reserved ranges per layer and a check that blocks raw values.
How it works
- 1 Find every z-index in the codebase, including inline styles and values buried in third-party overrides, and list them with the component that owns each. The count is usually higher than anyone expects and several will be arbitrary large numbers.
- 2 Reserve a range for each layer rather than assigning single values, so a new dropdown can slot between existing ones without renumbering everything above it. Leave real gaps between ranges.
- 3 Name each token after the layer it belongs to and derive the ordering from Elevation Layer Map. That feature decides what covers what; this one holds the numbers and stops them being invented locally.
Copy the prompt
No account needed
Add this feature to my app:
https://addthisfeature.com/x/z-index-registry
Spacing Scale
Spacing Scale
Reduce the app's spacing to a small set of steps that repeat across every surface.
What it does
A named spacing scale covering gaps, padding, and section rhythm, with every existing value in the app mapped onto it.
How it works
- 1 Collect every spacing value currently in the codebase and count how often each appears. The result is usually a handful of genuine intentions surrounded by dozens of near-misses that were nudged once and never revisited.
- 2 Define a scale that is fine at the small end, where control padding lives, and coarse at the large end, where section separation lives. A linear scale gives too many indistinguishable large steps and too few small ones.
- 3 Separate the tokens used inside a component from the ones used between components and between page sections, and name them so the difference is obvious. The same number serving both purposes means a change to button padding also changes the gap between sections.
Copy the prompt
No account needed
Add this feature to my app:
https://addthisfeature.com/x/spacing-scale
Shadow Scale
Shadow Scale
Replace ad hoc shadows with a small set tied to what each surface actually is.
What it does
A fixed ladder of shadow tokens, each named for an elevation role rather than a blur radius.
How it works
- 1 Collect every shadow currently declared anywhere in the app and group them by what they sit on — a resting card, a hovered card, a dropdown, a dialog, a toast. Most apps have a dozen near-identical values that collapse into four or five roles.
- 2 Name each step for its role, not its appearance. A token called menu tells the next person which surfaces may use it; a token called shadow-md-2 does not.
- 3 Use a single light source for the whole scale, so offset, blur, and spread grow together as elevation rises. Two shadows lit from different directions on the same screen read as a rendering bug.
Copy the prompt
No account needed
Add this feature to my app:
https://addthisfeature.com/x/shadow-scale
How it works
-
1
Copy the link
Grab the Markdown instruction URL for this feature.
-
2
Give it to your AI
Paste it into Claude Code, Cursor, v0, Lovable — whatever you build with.
-
3
It inspects, then implements
Your agent reads your existing app first, then adds the feature to fit it.
Works with your stack
These instructions are written to adapt. They tell the agent to detect your framework, match your existing design system, and reuse what you already have — rather than assuming a particular stack.
Need it tighter than that? Customize the feature and tell it exactly what you're running.