Skip to content

🎯 refactor: Hold ClickHouse Colors at Their Click UI Values - #16821

Merged
berry-13 merged 16 commits into
devfrom
berry-13/theme-ch-parity-100
Oct 8, 2026
Merged

berry-13 merged 16 commits into
devfrom
berry-13/theme-ch-parity-100

Conversation

@berry-13

@berry-13 berry-13 commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The ClickHouse reference theme departed from Click UI in about 28 colour roles to keep WCAG contrast, and the drift spec recorded each departure as a documented mismatch. By owner decision ClickHouse now matches Click UI over WCAG contrast: every role takes the Click UI token value exactly in light and dark, and each value cites its token. The default, dark and high-contrast themes are untouched. ClickHouse file-type tiles map to distinct Click UI palette tokens (document, sheet, code, artifact, audio, video, generic). Roles Click UI draws with alpha (the danger alert fill and edge, the sidebar hover and selected fills) are held as the token composited on the surface it sits on, since a role holds an opaque triplet. text2xl takes typography.font.sizes.6 (2rem), so text-3xl becomes a theme role (default 1.875rem, unchanged) and a spec holds the type scale monotonic in every bundled theme; listMaxHeight moves to the not-expressible list (3 entries, tracked at berry-13#282) because Click UI caps its select list at the popover's available height, which a length role cannot express.

The snapshot is re-pinned to Click UI v0.14.0 (c161141f4e, no token files changed), and the Lia sprite palette (client/src/components/Lia/engine/*.ts) is added to allowlist entry 4 as artwork (10 entries or fewer).

A new surface-sidebar role (default surface-primary-alt, so the default themes are unchanged) paints the sidebar panel, the mobile drawer, its list fade and the conversation row ring. ClickHouse sets it from sidebar.main.color.background.default (#ffffff / #1f1f1c), recomposites the sidebar hover and selected fills on it, and takes the drawer edge from sidebar.main.color.stroke.default; the search pill moves to field.color.background.default in light so it still steps off the white sidebar. The DataTable header already paints table-header-fill, which ClickHouse sets from Click UI's table header token, so nothing more was needed there. Fixes berry-13#141.

Roles that now fall below WCAG, each pinned with its measured ratio in clickhouse.spec.tsx. Light, AA text: text-secondary, -alt and -tertiary on the info, warning and error subtle fills (4.05 to 4.42:1), status-success on its fill (4.27:1), status-info on its fill (3.32:1), link and link-prose on the page (3.84:1, 3.58:1 on the secondary surface). Light, 3:1 non-text: border-xheavy (2.03:1), prose-bullet and prose-quote-bar (2.03:1, 1.64:1 on the user bubble), chart series 2, 3, 5 and 7 (2.65, 1.72, 1.19 and 1.95:1), border-control (1.24:1) and switch-unchecked (1.56:1). Dark, 3:1 non-text: border-xheavy (1.62:1), prose-bullet and prose-quote-bar (1.62:1, 1.26:1 on the user bubble), border-control (1.50:1) and switch-unchecked (2.90:1). Dark cards (#1f1f1c, the canvas) and dark tooltips (#282828) follow Click UI's own definitions, so they sit close to the canvas. Dark surface-overlay is now Click UI's #606060 scrim, which lifts the page rather than dimming it, and series 1 equals status-info in light because Click UI uses one blue for both.

Type of change

  • Refactor
  • Tests / tooling / CI

Testing

Tested environments/configuration: Chromium, desktop light and dark plus mobile; the ClickHouse theme loaded from librechat.yaml on a local lc pair, light and dark.

Automated tests:

  • npx jest src/theme --maxWorkers=2 in packages/client: 12 suites, 559 tests pass (clickui drift spec reports 0 mismatch and 0 unsourced colour roles per mode; color-diff.cjs agrees)
  • npx eslint on the touched theme files, prettier --check, node scripts/sort-imports.mts --check, and npx tsc --noEmit in packages/client: clean
  • Semantic contrast specs no longer assert the floors ClickHouse deliberately gives up; clickhouse.spec.tsx pins every sub-floor pair instead, including border-control and the switch track
  • reviewctl precheck: every step passes (the config-migration step failed once on a Redis connection and passed on rerun)
  • reviewctl verify --all --browsers chromium: the 12 contract scenarios pass (ClickHouse scenarios updated to the Click UI values; the default-theme layers scenario is unchanged and passes)

Screenshots / recordings

No user-facing change for any deployment that does not select the ClickHouse theme. The sidebar surface is visible under ClickHouse only; light and dark were checked in the browser.

Risks

ClickHouse contrast regressions listed above are intentional. text-3xl headings now follow the theme scale, so none render smaller than text-2xl under ClickHouse.

Checklist

  • I reviewed my own changes
  • Relevant tests have been added or updated
  • Existing relevant tests pass
  • The change does not introduce new warnings or errors
  • User-facing or complex behavior is documented where necessary
  • Required dependency changes have been merged/published
  • Required documentation PR: N/A

Copilot AI balanced review requested due to automatic review settings October 6, 2026 14:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codegraph-librechat codegraph-librechat Bot added the 🗺️ Design Tokens codegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9) label Oct 6, 2026
@berry-13
berry-13 force-pushed the berry-13/theme-ch-parity-100 branch from 752028b to 7e5815b Compare October 7, 2026 10:12
@berry-13
berry-13 marked this pull request as ready for review October 7, 2026 10:12
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-07T21:20:03.186564Z 68e1349 New commits
🔒 Security Review ✅ Completed 2026-10-07T10:15:25.043133Z 7e5815b Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e5815bad5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +16 to +17
* names a value for holds it exactly, by owner decision, including where that value
* misses a WCAG floor; `clickhouse.spec.tsx` pins each pair that does. A token Click UI

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve WCAG contrast in the ClickHouse theme

When a deployment selects the ClickHouse theme, this policy deliberately replaces accessible adjustments with values that fail the relevant contrast floors: in light mode link/link-prose fall to 3.58–3.84:1, border-control falls to 1.16–1.24:1, and several series marks fall as low as 1.19:1; dark controls and prose markers also fall below 3:1. Updating the tests to accept those values does not keep normal-sized links, field boundaries, switches, and graphical cues perceivable, so retain accessible semantic-role values rather than letting exact Click UI parity override the floors.

AGENTS.md reference: AGENTS.md:L49-L52

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changed: by owner decision the ClickHouse theme matches Click UI over WCAG contrast (default and high-contrast themes keep theirs). Every sub-floor pair is pinned with its measured ratio in clickhouse.spec.tsx and listed in the PR body.

['rgb-border-menu', 'rgb-border-light', 'rgb-border-light'],
['rgb-surface-composer', 'rgb-surface-chat', 'rgb-surface-chat'],
['rgb-surface-search', 'rgb-surface-secondary', 'rgb-surface-secondary'],
['rgb-surface-sidebar', 'rgb-surface-primary-alt', 'rgb-surface-primary-alt'],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive the light drawer edge from the new sidebar role

When a custom light ThemeDefinition sets the new rgb-surface-sidebar role but omits rgb-drawer-edge, this entry resolves the panel color correctly, but resolveTheme's drawerEdgeSource still consults only rgb-surface-primary-alt. Because applyResolvedTheme writes the complete resolved palette, the edge remains LibreChat's bundled color rather than the custom drawer fill, producing a stray trailing border on the mobile drawer. Prefer rgb-surface-sidebar there, with rgb-surface-primary-alt retained as the legacy fallback.

AGENTS.md reference: AGENTS.md:L147-L151

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7ef05ec: the light drawer edge now derives from rgb-surface-sidebar, falling back to rgb-surface-primary-alt, with a registry spec.

textLg: '1.125rem', // typography.font.sizes.4
textXl: '1.25rem', // typography.font.sizes.5
text2xl: '1.5rem', // LibreChat's: Click UI's next step (sizes.6, 2rem) passes the unthemed text-3xl
text2xl: '2rem', // typography.font.sizes.6

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep themed title text inside its fixed-height input

With the ClickHouse theme selected, the workspace project-name editor renders the shared Input title variant as h-theme-field-lg text-2xl. That field remains 3rem tall and includes two 0.2813rem paddings plus its borders, while this change makes the text line itself 3rem tall (2rem at leading2xl: 1.5), so the editable title no longer fits its content box and is vertically clipped. Increase the large field height or give the title variant compatible leading/padding rather than enlarging this step independently of its control geometry.

AGENTS.md reference: AGENTS.md:L148-L151

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7ef05ec: ClickHouse sets fieldHeightLg to 3.6876rem so the 3rem title line, field padding and stroke fit; sourced in the Click UI drift spec.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Lighthouse CI failed. The last 80 log lines contain the measured budgets and assertion failures.


[WebServer] 2026-10-07 11:28:32 info: [StreamServices] Created in-memory stream services

[WebServer] 2026-10-07 11:28:32 info: [GenerationJobManager] Configured with in-memory stores

[WebServer] 2026-10-07 11:28:32 info: HTTP server timeout configuration

[WebServer] 2026-10-07 11:28:32 info: Server listening at http://localhost:3080

[WebServer] 2026-10-07 11:28:32 info: [MCPServersRegistry] Creating new instance

[WebServer] 2026-10-07 11:28:32 info: OAuth reconnect manager initialized successfully.

[WebServer] 2026-10-07 11:28:32 info: Created collection: projects

🤖: global setup has been started
🤖: using baseURL http://localhost:3080
🤖: using E2E user: testuser@example.com
[WebServer] 2026-10-07 11:28:34 info: [agent-triggers] durable delivery engine started

[WebServer] 2026-10-07 11:28:35 info: [schedules] engine started

[WebServer] 2026-10-07 11:28:35 info: Server readiness checks passing.

🤖: 🗝  authenticating user: testuser@example.com
🤖: ✔️  localStorage: set Nav as Visible /home/runner/work/LibreChat/LibreChat/e2e/storageState.json
🤖: ✔️  user successfully registered
[WebServer] 2026-10-07 11:28:48 info: [Login] [Login successful] [Username: testuser@example.com] [Request-IP: ::1] {"requestId":"5447f3be-fc72-48a5-ac36-8eac1236f809","request_id":"5447f3be-fc72-48a5-ac36-8eac1236f809","request_method":"POST","request_path":"/api/auth"}

🤖: ✔️  user successfully authenticated
🤖: ✔️  authentication state successfully saved in /home/runner/work/LibreChat/LibreChat/e2e/storageState.json
🤖: global setup has been finished

Running 1 test using 1 worker

[1/1] [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets
[chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets
Lighthouse run 1/3 wrote /home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-1.report.json

Lighthouse run 2/3 attempt 1 did not complete, retrying: Command failed: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/runner/work/LibreChat/LibreChat/node_modules/lighthouse/cli/index.js http://localhost:3080/c/16390000-0000-4000-8000-000000000001 --quiet --preset=desktop --throttling-method=provided --only-categories=performance --chrome-flags=--headless=new --extra-headers={"Cookie":"token_provider=librechat; refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjZhYzYyY2VjOGM4YzBiNzVkY2Q2OWQwZiIsInNlc3Npb25JZCI6IjZhYzYyY2Y0OGM4YzBiNzVkY2Q2OWQzMCIsImlzc3VlZEF0TXMiOjE3OTEzNzI1MzIwOTQsImlhdCI6MTc5MTM3MjUzMiwiZXhwIjoxNzkxMzc2MTMyfQ.X8dfb9st_z47wAqy70kNcyfrj1vjsyY-wu-HuTpizik"} --output=json --output=html --output-path=/home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-2

  1) [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets 

    Error: Command failed: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/runner/work/LibreChat/LibreChat/node_modules/lighthouse/cli/index.js http://localhost:3080/c/16390000-0000-4000-8000-000000000001 --quiet --preset=desktop --throttling-method=provided --only-categories=performance --chrome-flags=--headless=new --extra-headers={"Cookie":"token_provider=librechat; refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjZhYzYyY2VjOGM4YzBiNzVkY2Q2OWQwZiIsInNlc3Npb25JZCI6IjZhYzYyY2Y0OGM4YzBiNzVkY2Q2OWQzMCIsImlzc3VlZEF0TXMiOjE3OTEzNzI1MzIwOTQsImlhdCI6MTc5MTM3MjUzMiwiZXhwIjoxNzkxMzc2MTMyfQ.X8dfb9st_z47wAqy70kNcyfrj1vjsyY-wu-HuTpizik"} --output=json --output=html --output-path=/home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-2
    Runtime error encountered: Something went wrong with recording the trace over your page load. Please run Lighthouse again. (NO_NAVSTART)


    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/error-context.md

    attachment #3: trace (application/zip) ─────────────────────────────────────────────────────────
    e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/trace.zip
    Usage:

        npx playwright show-trace e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────


🤖: global teardown has been started
2026-10-07 11:30:37 �[32minfo�[39m: �[32mMongo Connection options�[39m
2026-10-07 11:30:37 �[32minfo�[39m: �[32m{�[39m
�[32m  "bufferCommands": false�[39m
�[32m}�[39m
🤖:  ✅  Connected to Database
🤖:  ✅  Found user in Database
🤖:  ✅  Deleted 1 convos & 2 messages
🤖:  ✅  Deleted user from Database
🤖: global teardown has been started
2026-10-07 11:30:38 �[32minfo�[39m: �[32mMongo Connection options�[39m
2026-10-07 11:30:38 �[32minfo�[39m: �[32m{�[39m
�[32m  "bufferCommands": false�[39m
�[32m}�[39m
🤖:  ✅  Connected to Database
🤖:  ⚠️  User not found in Database
  1 failed
    [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets 

Open the full run

@berry-13
berry-13 force-pushed the berry-13/theme-ch-parity-100 branch from 9392f84 to 05b56cc Compare October 7, 2026 14:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05b56cc6f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* on the same surface, so the fill no longer separates them on its
* own and the boundary has to be a line in every theme. */
'border-border-light bg-surface-primary-alt min-h-0 flex-1 overflow-hidden border-r',
'border-border-light bg-surface-sidebar min-h-0 flex-1 overflow-hidden border-r',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Repaint all sidebar panel layers with the sidebar role

When ClickHouse is active and the user opens Schedules, Memories, MCP Builder, or Bookmarks, this nav now uses surface-sidebar, but the shared PanelContent fade and PanelFooter still paint surface-primary-alt (client/src/components/ui/PanelContent.tsx:75 and PanelFooter.tsx:18). Since ClickHouse deliberately makes those colors different, scrollable panels show an off-color bottom gradient and panels with footers show a contrasting strip; pass/use surface-sidebar for these sidebar-owned layers as well.

AGENTS.md reference: AGENTS.md:L142-L151

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ee5ad0f: PanelContent's fade and PanelFooter now paint surface-sidebar, which equals surface-primary-alt in the default, dark and high-contrast themes. Checked under ClickHouse in light and dark: nav, fade and footer share one colour.

Comment on lines 430 to +432
isActiveConvo || isPopoverActive
? 'ring-surface-nav-selected'
: 'ring-surface-primary-alt group-hover:ring-surface-nav-hover',
: 'ring-surface-sidebar group-hover:ring-surface-nav-hover',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Move the pull-request status ring to the sidebar role

When pull-request badges are enabled under ClickHouse, this updates the unread dot's idle ring for the new sidebar surface, but the adjacent PullRequestRowMark still defines its idle ring as ring-surface-primary-alt (client/src/components/Chat/PullRequest/RowMark.tsx:17). Because surface-sidebar is white/#1f1f1c while surface-primary-alt is #f6f7fa/#282828, the CI dot retains a visible halo on otherwise idle sidebar rows; update that marker to use the same sidebar role.

AGENTS.md reference: AGENTS.md:L142-L151

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ee5ad0f: the pull-request row mark's idle ring moves to surface-sidebar like the unread dot; the RowMark spec follows.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee5ad0f3f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

'rgb-border-menu',
'rgb-surface-composer',
'rgb-surface-search',
'rgb-surface-sidebar',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Invalidate old resolved-theme caches for new roles

When a signed-in user reloads after upgrading from the previous release, the added surface-sidebar, text3xl, and leading3xl properties are absent from their serialized deployment-theme entry, but both readThemeCache and the pre-bundle script in client/index.html still accept cache version 2. The boot paint therefore falls back to the bundled values—for example, cached ClickHouse renders the sidebar as surface-primary-alt and text-3xl at 1.875rem—until React replaces it with the new white sidebar and 2rem type scale, reintroducing the flash this cache exists to prevent. Bump the cache version in both readers when extending the resolved property schema.

AGENTS.md reference: AGENTS.md:L49-L52

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already covered on dev by #16819: the cache version is derived from themeRoleFingerprint(), so adding surface-sidebar, text3xl and leading3xl changes it (hash 1iop44p against xbzud8 without them) and old entries are dropped. This head is rebased onto it (68e1349) and also bumps THEME_CACHE_EPOCH to 2 because the ClickHouse values changed without role changes. themeCache and Providers specs pass (136 tests).

@berry-13
berry-13 force-pushed the berry-13/theme-ch-parity-100 branch from ee5ad0f to 68e1349 Compare October 7, 2026 21:17
@berry-13
berry-13 merged commit 248dae1 into dev Oct 8, 2026
56 of 58 checks passed
@berry-13
berry-13 deleted the berry-13/theme-ch-parity-100 branch October 8, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🗺️ Design Tokens codegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants