Skip to content

fix: give a darkHue-only color its own hue var in both schemes - #87

Merged
tenphi merged 1 commit into
mainfrom
fix/dark-hue-var-and-extreme-hc
Aug 4, 2026
Merged

fix: give a darkHue-only color its own hue var in both schemes#87
tenphi merged 1 commit into
mainfrom
fix/dark-hue-var-and-extreme-hc

Conversation

@tenphi

@tenphi tenphi commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Follow-up fixes that were left uncommitted when #84 (darkHue / darkSaturation) and #82 (extreme tone with a base) were merged. Re-applied on top of current main — the original changesets were already consumed by the version-packages PRs, so this ships its own patch changeset.

The bug

A color that authored only darkHue (no light hue) got the theme's --{name}-hue var as its var() reference in both schemes. The per-color --{color}-hue declaration was still emitted in the dark block — but nothing read it, so the dark hue was silently dropped.

theme.colors({ surface: { tone: 35, darkHue: 90 } });
theme.css({ format: 'oklch', splitHue: true, name: 'brand' });

Before, dark got --surface-hue: 90; next to a --surface-color that still interpolated var(--brand-hue).

A color that authors a hue in either scheme now gets its own hue custom property in both, tracking the theme hue (--surface-hue: var(--brand-hue)) in the scheme it did not author — so the shared reference stays valid and runtime re-skinning still works. Applies to css({ splitHue: true }) and the Tasty token map alike; darkHueDeclarations becomes buildHueDeclarations, returning both schemes so the two sides can't drift apart again.

Colors that author a light hue are unaffected — they already got their own var in both schemes.

Docs correction

docs/api.md claimed high-contrast variants were exempt from the extreme-tone light-shift replay because "their window is already the full range". They aren't exempt — they follow the same rule; the full-range window just means the replay usually reproduces the plain mapping, and only diverges when the base itself sits asymmetrically across schemes (a mode: 'fixed' or contrast-solved base). Added a test pinning that divergence, plus assertions locking the exact tone values docs/api.md cites.

No behavior change in the resolver

extremeDarkTone was already only called with isDark === true, where baseTone was the dark variant's tone — so dropping the redundant baseDarkTone parameter, moving the extreme branch inside the absolute/extreme arm, and folding the extreme's tone clamp into the solve literal are all cleanups. Verified: reverting the source fixes leaves only the new splitHue test failing.

Checks

pnpm test (353 passed), pnpm run typecheck, pnpm run lint, pnpm run format:check — all clean.

🤖 Generated with Claude Code

A color that authored only `darkHue` referenced the theme's `--{name}-hue`
var in both schemes, so the `--{color}-hue` declaration emitted in the dark
block was never read and the dark hue was silently dropped from `splitHue`
exports. A color that authors a hue in either scheme now gets its own hue
custom property in both, tracking the theme hue in the scheme it did not
author, so the shared `var()` reference stays valid and runtime re-skinning
keeps working. Covers `css({ splitHue: true })` and the Tasty token map.

Also correct the `tone: 'max'` / `'min'` with a `base` docs: high-contrast
variants are not exempt from the light-shift replay. They follow the same
rule, and because their window is already the full range the replay
reproduces the plain mapping unless the base itself sits asymmetrically
across schemes. Behavior unchanged — `extremeDarkTone` already read the
dark base variant, so dropping its redundant `baseDarkTone` parameter and
folding the extreme's tone clamp into the solve literal are cleanups.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📦 Snapshot release

Published 0.0.0-snapshot.13fe6d5.

pnpm add @tenphi/glaze@0.0.0-snapshot.13fe6d5

@tenphi
tenphi merged commit b5eb888 into main Aug 4, 2026
3 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant