Skip to content

feat(configurator): paste any colour format + always-visible hex reference - #636

Merged
jackgranatowski merged 3 commits into
mainfrom
claude/configurator-controls-audit-zqi10q
Jul 19, 2026
Merged

feat(configurator): paste any colour format + always-visible hex reference#636
jackgranatowski merged 3 commits into
mainfrom
claude/configurator-controls-audit-zqi10q

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related quality-of-life improvements to the configurator's colour editing, aimed at hex-native workflows.

1. Paste any CSS colour, stored canonical. Colour fields previously accepted only the token's own format, so a designer with a brand hex had to pre-convert to OKLCH by hand. Now any CSS colour the browser understands — hex (3/4/6/8), rgb()/rgba(), hsl(), named colours, hwb, lab()/lch(), color(), even oklab() — is normalised into the field's target space on commit. Conversion uses the live preview iframe's own colour engine via relative-colour syntax (oklch(from <input> l c h)), so the result matches exactly what the browser paints — no colour-math library, no drift. var() references and already-canonical values pass through untouched; unparseable text is kept verbatim so a paste is never silently dropped.

2. Always-visible hex reference. After a pasted hex is normalised to oklch(), the recognisable colour "disappeared". The real gamut-mapped sRGB hex now sits next to the canonical value in both the brand desk and the generic colour input (e.g. oklch(0.744 0.181 56.4) · #ff8801), so a hex-native workflow always has its reference. Resolved off the preview canvas, reactive as sliders/values change.

Verified in-browser: pasting #ff8800 into the Primary source Raw field stores oklch(0.744 0.181 56.4), the L/C/H sliders populate, and the header reads … · #ff8801 (the round-trip differs by 1/255 — imperceptible).

Type

  • feat

Checklist

  • Conventional Commit messages — enforced by commitlint
  • Configurator-only (Svelte/TS); no core/*.css, no framework tokens, no version change
  • svelte-check passes (0 errors)
  • Configurator unit tests pass (191/191; adds tests/colorConvert.test.ts, 5 cases)
  • check:doc-refs passes (CHANGELOG under ## Unreleased)
  • Breaking changes include migration docs — n/a

Notes

New configurator/src/lib/colorConvert.ts: colorSpaceOf() classifies a value; convertColor() resolves the relative-colour expression through the probe and reformats to the compact convention (alpha preserved); normalizeColorInput() is the commit helper; previewHex() returns the painted sRGB hex for the reference. Wired into OklchColorDesk (Raw field + header) and ColorInput (text commit, native picker output, display). Pure classification/pass-through/fallback logic is unit-tested; the browser-native conversion itself is verified at runtime (can't run headless without the preview iframe).

No version bump — versioning is handled manually.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Color fields now accept CSS color formats including hex, rgb(), hsl(), named colors, lab(), lch(), and color().
    • Entered colors are automatically converted to the appropriate canonical format.
    • CSS variable references and already-canonical values remain unchanged.
    • Color inputs now display a hexadecimal preview for easier reference.
  • Bug Fixes
    • Improved handling of pasted, blurred, and picker-selected color values.
    • Empty color inputs now reset correctly.

claude added 2 commits July 19, 2026 17:17
…cal space

Colour fields accepted only the token's own format, so a designer with a
brand hex had to pre-convert to OKLCH by hand. Now any CSS colour the
browser understands — hex (3/4/6/8), rgb(a), hsl(a), named, hwb, lab/lch,
color(), even oklab — is normalised into the field's target space on
commit, using the live preview iframe's colour engine via relative-colour
syntax so the result matches exactly what gets painted.

- New lib/colorConvert.ts: colorSpaceOf() classifies a value; convertColor()
  resolves oklch(from <input> l c h) / oklab(from …) through the probe and
  reformats to the compact convention (alpha preserved); normalizeColorInput()
  is the commit helper — var() refs and already-canonical values pass
  through, foreign colours convert, unparseable text is kept verbatim.
- OklchColorDesk Raw field and ColorInput (text commit + native picker
  output) route through it. The desk's L/C/H sliders now populate from a
  pasted hex.

Configurator-only; no framework tokens or version touched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
…colour

After a pasted hex is normalised to oklch(), designers lost sight of the
colour they recognised. Show the real gamut-mapped sRGB hex next to the
canonical value in both the brand desk and the generic colour input, so a
hex-native workflow always has its reference (e.g. "oklch(0.744 0.181 56.4)
· #ff8801"). Resolved off the preview canvas, reactive via previewVersion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 36df93ed-245a-470d-887f-9cc83a5fe1d1

📥 Commits

Reviewing files that changed from the base of the PR and between 7e0625f and 02beabe.

📒 Files selected for processing (3)
  • configurator/src/components/inputs/ColorInput.svelte
  • configurator/src/lib/colorConvert.ts
  • configurator/tests/colorConvert.test.ts
📝 Walkthrough

Walkthrough

The configurator adds shared CSS color classification, canonical OKLCH/OKLAB conversion, safe reference handling, and hex previews. Both color editors use the normalization flow for commits and display resolved hex values, with tests covering classification and unavailable preview engines.

Changes

Color normalization and configurator integration

Layer / File(s) Summary
Color normalization engine
configurator/src/lib/colorConvert.ts, configurator/tests/colorConvert.test.ts
Adds color-space classification, browser-based conversion, canonical formatting, reference pass-through, hex preview resolution, and tests for fallback behavior.
General color input integration
configurator/src/components/inputs/ColorInput.svelte
Routes picker and text commits through target-space normalization and displays derived hex references for non-variable values.
OKLCH editor integration
configurator/src/components/inputs/OklchColorDesk.svelte, CHANGELOG.md
Normalizes raw inputs to OKLCH, displays reactive hex previews, updates commit handling, and documents accepted CSS color formats.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ColorInput
  participant normalizeColorInput
  participant PreviewIframe
  participant TokenEditor
  User->>ColorInput: enter or pick CSS color
  ColorInput->>normalizeColorInput: commit input and target space
  normalizeColorInput->>PreviewIframe: resolve and convert color
  PreviewIframe-->>normalizeColorInput: canonical color or unresolved result
  normalizeColorInput->>TokenEditor: store canonical or pass-through value
Loading

Possibly related PRs

Suggested labels: codex

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main configurator changes: accepting any color format and showing an always-visible hex reference.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/configurator-controls-audit-zqi10q

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Jul 19, 2026
@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds two quality-of-life improvements to the configurator's colour editing: any CSS colour format (hex, rgb, hsl, named, lab, lch, etc.) can now be pasted into colour fields and is normalised to the token's canonical space (OKLCH/OKLAB) via the browser's relative-colour syntax engine; and an always-visible sRGB hex reference is shown alongside the canonical value.

  • configurator/src/lib/colorConvert.ts (new): provides colorSpaceOf, convertColor, normalizeColorInput, and previewHex, routing through the preview iframe's colour engine with a raw-text fallback when conversion fails.
  • ColorInput.svelte and OklchColorDesk.svelte: wired to normalizeColorInput on commit and now display a live hex badge next to the canonical value.
  • colorConvert.test.ts (new): 5 unit test cases covering pure classification and the pass-through/fallback path; a missing cross-space test case (oklab into oklch target) would have caught the gap in normalizeColorInput.

Confidence Score: 3/5

Mostly safe, but a logic gap in normalizeColorInput causes pasted oklab values to be stored unchanged in oklch fields, silently breaking the L/C/H sliders.

The cross-space conversion gap means pasting oklab into an oklch field stores the wrong format and leaves sliders stuck at hardcoded defaults. The rest of the feature is well-constructed.

configurator/src/lib/colorConvert.ts needs the cross-space branch fixed in normalizeColorInput, and a matching test case added to colorConvert.test.ts.

Important Files Changed

Filename Overview
configurator/src/lib/colorConvert.ts New colour conversion module; the cross-space pass-through in normalizeColorInput silently stores oklab in oklch fields, breaking sliders, and the format regex misses CSS none channels for achromatic colours.
configurator/src/components/inputs/ColorInput.svelte Adopts commit() for all colour commits and adds hex reference display; the oninput handler now triggers an iframe round-trip on every color picker drag tick.
configurator/src/components/inputs/OklchColorDesk.svelte Adds commitRaw() for the raw text field and an always-visible hex reference; straightforward and correct for the oklch-only context, but inherits the cross-space conversion gap from normalizeColorInput.
configurator/tests/colorConvert.test.ts Unit tests cover classification and safe pass-through/fallback behaviour; no cross-space test case (oklab into oklch target), which would have caught the gap in normalizeColorInput.
CHANGELOG.md Adds an Unreleased entry describing the new colour-paste feature; no version bump as noted in the PR description.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["User input (paste / picker / blur)"] --> B["commit() / commitRaw()"]
    B --> C["normalizeColorInput(value, target)"]
    C --> D{colorSpaceOf}
    D -->|"null (var ref / empty)"| E["Pass through unchanged"]
    D -->|"oklch or oklab (canonical)"| F{"space === target?"}
    F -->|"yes"| G["Pass through unchanged"]
    F -->|"no: cross-space BUG"| H["Pass through unchanged - wrong space stored"]
    D -->|"other (hex/rgb/hsl/named)"| I["convertColor(value, target)"]
    I --> J["resolveColor via preview iframe"]
    J -->|"starts with target prefix"| K["format to compact canonical string"]
    J -->|"null / wrong prefix"| L["Fallback: raw text preserved"]
    K --> M["onSet / onChange"]
    E --> M
    G --> M
    H --> M
    L --> M
    style H fill:#fca5a5,stroke:#dc2626
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["User input (paste / picker / blur)"] --> B["commit() / commitRaw()"]
    B --> C["normalizeColorInput(value, target)"]
    C --> D{colorSpaceOf}
    D -->|"null (var ref / empty)"| E["Pass through unchanged"]
    D -->|"oklch or oklab (canonical)"| F{"space === target?"}
    F -->|"yes"| G["Pass through unchanged"]
    F -->|"no: cross-space BUG"| H["Pass through unchanged - wrong space stored"]
    D -->|"other (hex/rgb/hsl/named)"| I["convertColor(value, target)"]
    I --> J["resolveColor via preview iframe"]
    J -->|"starts with target prefix"| K["format to compact canonical string"]
    J -->|"null / wrong prefix"| L["Fallback: raw text preserved"]
    K --> M["onSet / onChange"]
    E --> M
    G --> M
    H --> M
    L --> M
    style H fill:#fca5a5,stroke:#dc2626
Loading

Reviews (1): Last reviewed commit: "feat(configurator): always show a hex re..." | Re-trigger Greptile

Comment thread configurator/src/lib/colorConvert.ts
Comment thread configurator/src/components/inputs/ColorInput.svelte Outdated
Comment thread configurator/src/lib/colorConvert.ts
…debounce picker

Addresses review findings on the colour-paste feature:

- normalizeColorInput now converts a value whose canonical space differs from
  the target (e.g. an oklab() pasted into an oklch field), instead of storing
  it verbatim and leaving the desk's L/C/H sliders stuck on their defaults.
- format() accepts the CSS Color 4 `none` channel keyword (achromatic
  colours), treating it as 0, so those pastes convert instead of falling back
  to raw text.
- ColorInput's native colour picker stores the raw hex live on `input` (fast,
  no per-drag iframe round-trip) and canonicalises once on `change` when the
  picker closes — also avoids oklch round-trip thumb jitter.

Tests extended to cover cross-space conversion, the `none` channel, and alpha.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BRVgKfEYocPCHz9KU96FN
@jackgranatowski
jackgranatowski merged commit f98c11e into main Jul 19, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants