Derived roles
A role with derivedFrom: 'other-role-name' declares itself as a parametric child of another role. The engine's expand:family task fills the derived role from the parent's resolved value, with optional hueOffset to rotate around the OKLCH hue wheel.
Shape
| Field | Type | Meaning |
|---|---|---|
derivedFrom | string | Name of the parent role (must exist in roles[]). |
hueOffset | number | Degrees to rotate the parent's hue. Positive = clockwise on the OKLCH hue ring. |
What it does
expand:family runs after resolve:roles and before enforce:contrast. For each role with derivedFrom:
- Look up the parent's resolved OKLCH coordinates.
- Copy
LandC(clamped to the child's ownlightnessRange/chromaRange). - Rotate the parent's
hbyhueOffset(mod 360). - Reconstruct the child's RGB / hex from the rotated OKLCH.
The child inherits the parent's lightness and chroma; only hue differs. This is what makes a single brand seed produce an entire syntax-token family: syntax-string is brand shifted +120°, syntax-number is brand shifted +60°, etc.
What it means
Derivation encodes family relationships. A schema with text-strong derived from text says "text-strong is the strong tier of text, it lives where text lives, just shifted". A schema with syntax-keyword derived from brand says "all syntax tokens orbit the brand colour".
The engine guarantees that if the parent moves (because the user picked a different seed), every child moves with it on the same hue arc. Designers author the relationship once in the schema, and every palette the user produces preserves it.
How to author
- Use
derivedFromwhenever the child's identity depends on the parent's. Brand-derived syntax tokens, status-derived signal colours, text-derived emphasis tiers. - Pair
derivedFromwithlightnessRange/chromaRangeenvelopes that the inheritedL/Cwill land inside. The inherited values are clamped, so a too-narrow range will collapse the derivation back toward grey. - Pick
hueOffsetvalues that produce perceptually distinct results. Multiples of 30° (30,60,90,120,150,180, ...) keep the family ring-like. - Don't chain derivations more than two levels deep.
expand:familyis a single pass; a grandchild that derives from a child only sees the child's pre-expansion state, which is unusual but well-defined.
Related
- Hue lock: opposite knob, pin a role's hue regardless of seed.
- Lightness range and Chroma range: the envelopes the inherited values are clamped into.
- Role schemas overview.