fix: compile #current to the keyword again - #273
Merged
Conversation
3.3.0 made `#current` emit `var(--current-color)` so a token defined as
`#current` could be faded on Safari 16.4 rather than 18: relative colour syntax
takes a concrete origin from 16.4, while `oklch(from currentcolor …)` needs 18.
That traded away the property `#current` exists for.
The keyword resolves against the element that reads it, so a `#current` under an
ancestor that faded its own colour reads the *faded* colour. A ramp built on
`#current` depends on it — the disabled state is expressed once, in `color`, and
everything painted from `#current` below fades with it. The variable cannot do
that: a faded colour is deliberately never published into `--current-color`,
because resolving it a second time one level down would fade it twice. So a
reader saw through to the unfaded colour above and rendered at full strength.
Chromatic on cube-ui-kit measured it — a disabled chip at `oklab(… / 0.4)` in
3.2.0 came out `oklch(0.571 0.0971 280.3)`, full strength, in 3.3.0.
The variable stays, and keeps both improvements 3.3.0 brought it: every colour
publishes it rather than only a named token, and it is registered with
`initial-value: currentcolor` rather than `transparent`. Its job is narrower now
— it carries the inherited colour for consumers that need a colour rather than
the keyword, read as `$current-color` — and `#current` no longer goes through it.
What 3.3.0 set out to fix goes back to needing Safari 18: a token *defined* as
`#current` and then faded gives relative colour syntax a `currentcolor` origin.
That case is documented with its portable alternative — put the fade in the token
itself, `{ '#ink': '#current.5' }`, and it composes through `color-mix()` on the
Safari 16.2 floor. The two `#current` paths that matter are pinned by
computed-style tests in a real engine: a bare `#current` under a faded ancestor
lands at `.4`, and a `#current.18` nested under a `#current.4` at `.072`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
📦 Snapshot releasePublished |
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#currentcompiles tocurrentcoloragain, as it did before 3.3.0.What 3.3.0 changed and why it has to come back
#271 made
#currentemitvar(--current-color)so that a token defined as#currentcould be faded on Safari 16.4 rather than 18 — relative colour syntax takes a concrete origin from 16.4, whileoklch(from currentcolor …)needs 18.That traded away the property
#currentexists for. The keyword resolves against the element that reads it, so a#currentunder an ancestor that faded its own colour reads the faded colour. A ramp built on#currentdepends on it: the disabled state is expressed once, incolor, and everything painted from#currentbelow fades with it.A variable cannot do that. A faded colour is deliberately never published into
--current-color— resolving acolor-mix()overcurrentcolora second time one level down would fade it twice — so a reader saw through to the unfaded colour above it. Chromatic on cube-ui-kit measured the result on a disabledcurrent.primarychip:backgroundColoron the disabled chipoklab(0.571 0.0173617 -0.0955352 / 0.4)oklch(0.571 0.0971 280.3)— full strengthoklab(0.571 0.0173617 -0.0955352 / 0.4)What stays
The variable keeps both improvements #271 brought it, with a narrower job — it carries the inherited colour for consumers that need a colour rather than the keyword (hand-authored CSS, anywhere
currentcolorwill not do), read as$current-color:colorrather than the nearest token colour;initial-value: currentcolorrather thantransparent, so an unpublished reader still resolves against its own element;What goes back to needing Safari 18
The case #271 set out to fix: a token defined as
#currentand then faded —{ '#ink': '#current', fill: '#ink.5' }— gives relative colour syntax acurrentcolororigin. Works in Chrome and Firefox, Safari 18+. The portable alternative is now documented — put the fade in the token itself,{ '#ink': '#current.5' }, and it composes throughcolor-mix()on the Safari 16.2 floor.Tests
The
#currentblock inapplied-styles.test.tsxis rewritten against real computed styles, since every step here is a computed-value-time rule that CSS text cannot show:#currentunder an ancestor at#current.4lands at/ 0.4— the regression above;#current.18nested under a#current.4still lands at/ 0.072;$current-colortakes the nearest colour, literal or token, and stands in for the keyword where nothing published it;pnpm test2079 passing, typecheck, lint and prettier clean.🤖 Generated with Claude Code