Skip to content

Accent colours are not tokenised, so they keep dark-tuned values on light grounds #402

Description

@cevheri

Follow-up to #384. That PR moved every neutral colour behind a token — five surface levels, hairlines, control edges, a seven-step text ramp — and the migration is complete: one deliberate literal remains in src (ConnectionModal.tsx:829, a spinner inside a solid blue button). Accents were left out of scope, so they still carry the value that was tuned for a near-black ground.

What that costs in light

Measured in Chrome against a production build, resolving lab()/oklab() through a canvas so the numbers are the ones actually painted:

where classes ratio on its own ground
agent rail, active mode and workflow pills (AgentRail.tsx:1028, :1056) bg-blue-500/15 text-blue-300 1.46 : 1
agent rail Start / action buttons (:1098, :1222, :1305) text-blue-300 1.46 – 2.4 : 1
agent rail warnings (:457, :498, :1211, :1445) text-amber-300 ~2.0 : 1
results tab strip, active (BottomPanel.tsx:204) text-blue-400 2.26 : 1
query pill (QueryToolbar.tsx:60-61) text-blue-400 2.38 : 1
Explain affordance amber-500 on #fafafa 2.05 : 1

bg-blue-500/15 over #0a0a0a lands near #1a2233, and blue-300 over that is comfortable. The same tint over white lands near #dbe8fb, and blue-300 over that is 1.46:1 — a chip you can see and a word you cannot read.

Calibration, so this is not read as a regression

I ran the same sweep in both themes over the whole studio surface. Light returns 33 text nodes below WCAG AA; dark returns 57. Low text contrast is this app's existing character rather than something the light theme introduced, and the bottom of the neutral ramp is symmetric by design — --studio-fg-subtle is #a1a1aa in light and #52525b in dark, both around 2.5:1, documented as the step for "decoration and hints".

So this issue is not "light mode is inaccessible". It is narrower: accent-on-accent-tint is the one failure class that light has and dark does not, because the accent values were selected against one ground and are now being asked to serve two.

Note this is separate from the chart series palette, which #384 did validate in both modes and which explicitly forbids using series colours as text.

Direction

The token layer already has the right shape; accents just need to join it. Something like an --studio-accent / --studio-accent-quiet pair selected per mode (blue-300 in dark, roughly blue-700 in light, with the tint adjusted to match), plus the amber equivalent for the warning slot, would let text-accent replace the literals the same way text-fg-muted replaced text-zinc-500.

Worth resisting the shortcut of sprinkling dark: variants at each call site — that is the state the neutral ramp was just rescued from, and it puts the decision back in 40 files.

Acceptance

cc @omerfarukbolat — context is freshest with you, but this is genuinely optional follow-up work, not a correction to what you shipped.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions