Skip to content

test(app,web): guard the picker block and the shared tokens against drift, and give the web the app's palette - #601

Open
khagele wants to merge 1 commit into
efiten:masterfrom
khagele:test/407-css-guards
Open

test(app,web): guard the picker block and the shared tokens against drift, and give the web the app's palette#601
khagele wants to merge 1 commit into
efiten:masterfrom
khagele:test/407-css-guards

Conversation

@khagele

@khagele khagele commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #407

The problem

app/src/styles/app.css and web/style.css carry blocks that are copies of each other by design, kept in step by hand, and only the ticker had a guard (#404). The picker rows and the --ch-* tokens did not, and the failure is quiet: nothing breaks, the two surfaces stop looking like each other, and the next port comes from whichever file was open (#225 was one).

My changes in this PR

In web/parity.test.js, plus one product change the guard asked for (below). A stopgap until #238 puts the tokens in one file both ship, and it says so.

  • A rule parser that splits on } after stripping comments, the fixed form from feat(app,web): make the receptions ticker readable at a glance #404 (eb404d9) efiten's comment on the issue asked for: adjacent :root rules both come out, and a comment naming a selector cannot satisfy a match. ruleDecls merges a selector that appears twice in cascade order.
  • The picker block: the row anatomy (.tl-check and its active states, .tl-name, .tl-meta, .tl-prefix, .tl-rssi, .tl-time, .tl-list, .tl-pinned, .tl-item) is pinned declaration for declaration; .tl-row is pinned apart from its density (padding, font-size: a sheet under a thumb against a popover under a mouse); every colour in those rules has to be a token, never a literal. The per-surface rules (.tl-panel, .tl-scroll, .tl-search, .tl-empty, .tl-clear, .tl-pinned-label's top margin) are listed in the test as such.
  • The tokens, per theme: the shared set (--ch-accent, --ch-accent-2, --ch-bg, --ch-text, --ch-muted, --ch-surface, --ch-border, the seven --ch-sig-*) must carry one value; every other token has to be listed as the app's own (--ch-basemap, --ch-bar-track, --ch-surface-thin, --ch-building) or the web's own (--ch-bar-h, --ch-input-bg), so an addition to either file is a decision the test asks for.
  • The web takes the app's --ch-border, --ch-surface and --ch-muted (Kasper, 2026-09-06: one design). They differed: a solid border against the app's translucent hairline, panels at 0.92 alpha against 0.82 and 0.86, and a dark-theme muted of #9aa against #8b98a9. Visible on the map as a hairline border and slightly more see-through panels; release note in both copies.
  • The node-position drift colours: both driftColor (app) and driftColorVar (web) are DOM-bound and not importable, so the pin reads the source and demands the same three tokens for the same kinds.

Verification

Suite Result
web vitest 517 passed (8 new), eslint clean
web e2e --fail-on-flaky-tests 199 passed (the control-theme and hover tests read the tokens)

Five mutations, each one test red: a changed .tl-check radius on the web, a changed dark --ch-sig-hot, a token added to the web that neither list names, a literal colour in .tl-rssi, and the drift tokens in another order.

Decisions worth a look

  • The three tokens were first recorded as per-surface; Kasper chose to align them to the app instead, so the guard pins fourteen tokens rather than eleven and nothing is left in a "differs on purpose" list.

🤖 Generated with Claude Code

…rift, and give the web the app's palette

Closes efiten#407. parity.test.js pins the picker row anatomy declaration for
declaration (density per surface), demands tokens rather than literal
colours there, pins fourteen shared --ch-* tokens per theme and lists
what each surface owns alone, and reads the node-position drift colours
out of both DOM modules. The web takes the app's border, surface and
muted values (Kasper, 2026-09-06: one design); release note in both
copies. Rules are parsed by splitting on '}' after stripping comments,
the fixed form from efiten#404.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@efiten

efiten commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Master moved: #569, #574, #580, #581 and #589 are merged, master is at f14d205. The conflict is the changelog arrays plus the tail of web/parity.test.js, where master (#580, #589) and this branch each append a describe block. Both are wanted; #580 and #589 were resolved by keeping master's block then this one's.

Notes below are from reading this PR's diff against master before those merges. Not a full audit, and the green checks are not part of it.

The two token lists here fail once #596 or #593 lands, whichever order they go in.

Both are list updates rather than code changes. The cheapest order is to land this one last and add --ch-building to SHARED (or drop it from APP_ONLY) and the twelve hues to SHARED at that point, so the guard is written against what is actually on both surfaces.

The guard itself reads well, and rulesOf splitting on } rather than a global regex is the right fix for the two-adjacent-:root-rules case. PER_SURFACE_TOKENS is declared after the describe that names it, which is fine because the read happens inside it(), after module evaluation.

Separately, the palette change moves dark --ch-muted from #9aa to #8b98a9 and both borders to rgba(...). Worth a contrast check on the muted text over --ch-surface at its new 0.82, since that is the pair the ticker's meta line uses.

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.

app,web: only the ticker block is guarded against CSS drift — the picker and the shared tokens are not

2 participants