Skip to content

fix(ui-core): the schema editor's swatch shows the colour the class is drawn in (#162) - #168

Merged
JArmandoAnaya merged 1 commit into
mainfrom
feat/beta2-162-derived-swatch
Jul 31, 2026
Merged

fix(ui-core): the schema editor's swatch shows the colour the class is drawn in (#162)#168
JArmandoAnaya merged 1 commit into
mainfrom
feat/beta2-162-derived-swatch

Conversation

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Closes #162. Fourth of the 0.0.1-beta.2 defect fixes.

The defect

A class with no declared colour showed the two colours it is actually drawn in as two different colours in the same row:

  • the dot beside the class name showed the real derived hue (pedestrian → teal, weather → gold);
  • the Colour swatch immediately to its right showed grey, captioned "Derived from the name."

The grey was an empty <input type="color"> falling back to its own default. hexOf passed a value through only when it already matched #rrggbb and answered a neutral otherwise — and classColor's derived branch answers hsl(hash % 360 72% 58%), so every derived class took the fallback. The class is not grey anywhere: the annotator draws it in the same teal, confirmed by drawing one.

So the editor contradicted both the dot two inches to its left and the canvas, in the one control whose entire job is to show what colour something is.

The fix

hexColor in frontend/ui-core/src/palette.ts converts rather than giving up. It is a notation change, never a second palette — criterion 4:

  • classColor stays the single spelling of the rule (ui-core: design system foundation — port v1's DESIGN.md visual contract (Tailwind v4 @theme tokens, shadcn/Radix primitives, class palette rule) #128's gate, which palette.test.ts still asserts by reference identity against the annotator's export);
  • this turns its answer into the four hex digits the input can take, handling #rrggbb, #rgb and both spellings of hsl(...);
  • it returns null for anything else, and the caller shows its neutral for that case alone. The kernel accepts any CSS spelling in LabelClass.color, so a schema authored elsewhere may legitimately hold rgb(255 0 0) or rebeccapurple, and shipping a CSS colour parser to fill in one input is not the trade. The dot still shows the truth there.

The half worth being careful about

Making the input display a colour must not make the class declare one. A schema version that pinned today's hash output would make every derived class look authored, and would change meaning if the palette rule ever moved.

So the guard is on the payload, not the control (criterion 2): after a save dirtied by something that is not the colour, the POST body still carries color: null for the derived class. "Derive" still clears a declared colour (criterion 3), and the swatch now follows it there too.

Verified by mutation: restoring the old #rrggbb-or-neutral fallback turns two named tests red — previews a derived class in the colour it is actually drawn in and Derive clears a declared colour back to the derived one, in the swatch too.

Every expectation is computed from the shipped palette rather than hardcoded, so a change to the rule moves both sides together and only a swatch that stopped reading classColor fails. screens.test.tsx gained a request-body capture for this — gallery.test.tsx already had one.

Ledger

  • Frontend only. No Python, no migration; openapi.json and the generated client byte-identical; FORMAT_VERSION still 12.
  • DESIGN.md records the conversion beside the palette rule it serves, since that file is the authority on it.

Checks run locally

  • pnpm test — 711 annotator + 123 ui-core vitest, 22 node:test
  • pnpm -r build, pnpm -r lint, pnpm -r typecheck — clean

…s drawn in (#162)

A class with no declared colour showed the two colours it is actually drawn in as
two different colours in the same row: the dot beside its name showed the real
derived hue, and the Colour swatch immediately to its right showed grey, captioned
"Derived from the name."

The grey was an empty `<input type="color">` falling back to its own default.
`hexOf` passed a value through only when it already matched `#rrggbb` and answered
a neutral otherwise — and `classColor`'s derived branch answers
`hsl(hash % 360 72% 58%)`, so *every* derived class took the fallback. The class is
not grey anywhere: the annotator draws it in that same teal.

`hexColor` in `palette.ts` converts instead. It is a **notation change, never a
second palette**: `classColor` stays the one spelling of the rule (#128's gate,
which `palette.test.ts` still asserts by reference identity), and this only turns
its answer into the four hex digits an input can take. `null` for anything it
cannot convert — the kernel accepts any CSS spelling in `LabelClass.color`, so a
schema authored elsewhere may hold `rgb(255 0 0)`, and shipping a CSS colour parser
to fill in one input is not worth it. The neutral survives for exactly that case,
which is the one it was always right about.

The care is in the second half: **making the input display a colour must not make
the class declare it.** An untouched save still sends `color: null` for a derived
class, and the test asserts that on the request payload rather than on the control
— a version that pinned today's hash output would make every derived class look
authored and would change meaning if the palette rule ever moved. "Derive" still
clears a declared colour, and the swatch now follows it there too.

Verified by mutation: restoring the old `#rrggbb`-or-neutral fallback turns two
named tests red.

`DESIGN.md` records the conversion beside the palette rule it serves.

Frontend only: no Python, no migration, `openapi.json` and the generated client
byte-identical, `FORMAT_VERSION` still 12.

Closes #162
@JArmandoAnaya
JArmandoAnaya merged commit 66c19ff into main Jul 31, 2026
12 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the feat/beta2-162-derived-swatch branch July 31, 2026 23:35
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.

ui-core: the schema editor's colour swatch shows grey for a derived class colour, contradicting its own dot

1 participant