Replace intent with the shared semantic colour contract (#309)
* Replace the intent colour contract with shared semantic roles
The public contract exposed an asymmetric `color.intent` tree: neutral,
accent, and danger received a full interactive ramp while info, success,
and warning received a feedback-only kit. That described how components
happened to use colour rather than what each colour styles and means.
Replace it with a property-first contract shared by all six roles. Every
role now gets subtle and solid background ramps with rest/hover/pressed,
a resting and a stronger interactive foreground, a guaranteed on-solid
foreground, and one state-free border — 60 leaves keyed off a single
canonical `SEMANTIC_ROLES` list that generation, mapping, validation,
diagnostics, and tooling all read.
`FAMILY_REQUIREMENTS` collapses to one uniform capability set, so all six
families are now gated on on-solid contrast where only neutral, accent,
and danger were before. This moves no existing colour: not one family
needed adapting, and steps 3-8, 11, and 12 generate identically for
info, success, and warning. The golden diff is additive only.
The validation matrix is now uniform per role: 90 hard checks (8
functional text, 60 role foregrounds, 18 on-solid, 2 focus, 2 control)
and 12 advisory semantic-border checks per mode.
`rest` is an explicit leaf because a path cannot be both a string leaf
and the parent of `hover` and `pressed`. Solid pressed deliberately
reuses solid hover; components carry the press through depth, finish, or
transform.
Refs #298, #299, #305
* Migrate components to the shared semantic colour contract
Move every consumer off `color.intent` onto the new background,
foreground, and border paths. Each old path has an exact new equivalent
resolving to an identical value, so this is visually a no-op: 218 of 222
visual captures are pixel-identical, and the four that differ are Token
Board captures whose height changed because the contract grew.
Button and IconButton keep their subtle, solid, ghost, hover, pressed,
disabled, pending, focus, material, and forced-colours behaviour. Button
derives its ramp type from the contract now rather than mirroring a
hand-flattened shape. Link uses the resting foreground at rest and the
stronger hover foreground for both hover and press, since the shared
contract carries no separate pressed content colour.
Fields and Combobox controls use the state-free accent and danger borders
while the functional focus ring stays independent on `border.focus`.
Selection stays a component pattern: selected options compose the accent
subtle ramp with a weight change and a check icon rather than a public
selected colour token. Disabled and pending controls preserve their
resting colours and suppress interaction states.
Add the coverage the specification asks for and the suites lacked:
Button's subtle ramp and its disabled suppression, a Field browser test
for the required indicator and error tone, and Combobox's
selected-plus-keyboard-focus composition.
Note that the advisory semantic borders sit at 1.62-2.19:1, below the 3:1
non-text gate, so they must never be a required state's only cue. The
three pre-existing violations of that rule are unchanged here and remain
tracked in #247.
Refs #298, #300, #301, #302, #303
* Document the shared semantic colour roles
Teach one shared role model instead of action and feedback intent groups:
the six roles and their meanings, the background and foreground state
grammar, the state-free borders, and the contrast guarantees. Publish the
old-to-new migration table, which is now the only place the old paths
appear.
Replace the intent-colours example with a role-colours example that shows
subtle and solid swatches per role, so the page demonstrates that every
role carries the full capability set.
Migrate the raw CSS consumers in the docs app, and fix a mis-cased
`--luke-color-intent-neutral-surface-subtleHover` reference that never
resolved against a real generated variable.
Correct the generation document: the loading skeleton maps to neutral
step 8, as implemented and tested, not step 7.
Refs #298, #304
Replace intent with the shared semantic colour contract (#309)
* Replace the intent colour contract with shared semantic roles
The public contract exposed an asymmetric `color.intent` tree: neutral,
accent, and danger received a full interactive ramp while info, success,
and warning received a feedback-only kit. That described how components
happened to use colour rather than what each colour styles and means.
Replace it with a property-first contract shared by all six roles. Every
role now gets subtle and solid background ramps with rest/hover/pressed,
a resting and a stronger interactive foreground, a guaranteed on-solid
foreground, and one state-free border — 60 leaves keyed off a single
canonical `SEMANTIC_ROLES` list that generation, mapping, validation,
diagnostics, and tooling all read.
`FAMILY_REQUIREMENTS` collapses to one uniform capability set, so all six
families are now gated on on-solid contrast where only neutral, accent,
and danger were before. This moves no existing colour: not one family
needed adapting, and steps 3-8, 11, and 12 generate identically for
info, success, and warning. The golden diff is additive only.
The validation matrix is now uniform per role: 90 hard checks (8
functional text, 60 role foregrounds, 18 on-solid, 2 focus, 2 control)
and 12 advisory semantic-border checks per mode.
`rest` is an explicit leaf because a path cannot be both a string leaf
and the parent of `hover` and `pressed`. Solid pressed deliberately
reuses solid hover; components carry the press through depth, finish, or
transform.
Refs #298, #299, #305
* Migrate components to the shared semantic colour contract
Move every consumer off `color.intent` onto the new background,
foreground, and border paths. Each old path has an exact new equivalent
resolving to an identical value, so this is visually a no-op: 218 of 222
visual captures are pixel-identical, and the four that differ are Token
Board captures whose height changed because the contract grew.
Button and IconButton keep their subtle, solid, ghost, hover, pressed,
disabled, pending, focus, material, and forced-colours behaviour. Button
derives its ramp type from the contract now rather than mirroring a
hand-flattened shape. Link uses the resting foreground at rest and the
stronger hover foreground for both hover and press, since the shared
contract carries no separate pressed content colour.
Fields and Combobox controls use the state-free accent and danger borders
while the functional focus ring stays independent on `border.focus`.
Selection stays a component pattern: selected options compose the accent
subtle ramp with a weight change and a check icon rather than a public
selected colour token. Disabled and pending controls preserve their
resting colours and suppress interaction states.
Add the coverage the specification asks for and the suites lacked:
Button's subtle ramp and its disabled suppression, a Field browser test
for the required indicator and error tone, and Combobox's
selected-plus-keyboard-focus composition.
Note that the advisory semantic borders sit at 1.62-2.19:1, below the 3:1
non-text gate, so they must never be a required state's only cue. The
three pre-existing violations of that rule are unchanged here and remain
tracked in #247.
Refs #298, #300, #301, #302, #303
* Document the shared semantic colour roles
Teach one shared role model instead of action and feedback intent groups:
the six roles and their meanings, the background and foreground state
grammar, the state-free borders, and the contrast guarantees. Publish the
old-to-new migration table, which is now the only place the old paths
appear.
Replace the intent-colours example with a role-colours example that shows
subtle and solid swatches per role, so the page demonstrates that every
role carries the full capability set.
Migrate the raw CSS consumers in the docs app, and fix a mis-cased
`--luke-color-intent-neutral-surface-subtleHover` reference that never
resolved against a real generated variable.
Correct the generation document: the loading skeleton maps to neutral
step 8, as implemented and tested, not step 7.
Refs #298, #304