Skip to content

🔇 feat: Let a Theme Quiet Decorative Borders - #16741

Merged
berry-13 merged 5 commits into
devfrom
berry-13/ch-theme-borders
Oct 5, 2026
Merged

berry-13 merged 5 commits into
devfrom
berry-13/ch-theme-borders

Conversation

@berry-13

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

Copy link
Copy Markdown
Collaborator

Summary

The ClickHouse theme draws more strokes than Click UI does. LibreChat outlines icon buttons, chips, avatar rings and the rail beside the sidebar, and stacks three or four hairlines inside one tool or marketplace card, where Click UI separates regions by fill. The decorative border values are already Click UI's own stroke.default, so the problem is how many borders are drawn, and a theme could not remove them without also removing the card, popover and dialog strokes Click UI keeps.

This adds two appearance roles, chromeBorderAlpha and insetBorderAlpha (default 1), and the border-chrome and border-inset utilities, which are border-light at those shares. ClickHouse sets both to 0; the 1px box stays, so layout and hover geometry do not move, and the bundled themes draw exactly the border-light they drew before. Call sites that Click UI draws borderless move onto them: outlined icon buttons and the header action in Button, header pills, skill and quote chips, the marketplace card's avatar ring, category chip and footer rule, tool-card inner dividers and nested thought boxes, the rail rule beside the sidebar, and the settings dialog title rule. The Settings dialog also picks up --theme-dialog-stroke, so it is stroked like every other dialog in ClickHouse.

Fields keep their 3:1 edge: the sign-in, registration and password forms drop their border-light override and take the Input primitive's own border-control, and the search field and the agent builder's model trigger move to border-control too (equal to border-light in the bundled themes).

Type of change

  • Feature

Testing

Tested environments/configuration:

  • Browser: Chromium, 1440x900, light and dark
  • Feature flags: interface.theme: clickhouse and the default theme

Automated tests:

  • cd packages/client && npx jest (947 passed), cd client && npx jest --findRelatedTests <changed files> (7196 passed), data-provider theme specs
  • Added Button, tokens, registry and ClickHouse theme specs, and e2e/specs/mock/scenarios/chrome-border.spec.ts (default light/dark unchanged, ClickHouse light/dark draw nothing and keep the 1px box, a theme with its own shares)
  • npm run static-checks -- --against origin/dev passes; eslint-suppressions.json counts only go down
  • Manual: default-theme chat and settings screens compared with dev, maximum channel difference 2 on anti-aliased edges

Screenshots / recordings

Before and after screenshots below (ClickHouse, light and dark).

Risk / compatibility

Stacked on the focus-subtle PR. AddMultiConvo now renders the shared Button (header-action) inside TooltipAnchor, so it is a real button with the shared hover fill instead of a styled role="button" div. The chat direction toggle and the legacy parameters button keep border-light: both sit on primitives that reject a border override.

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 (packages/client/src/theme/README.md)
  • Required dependency changes have been merged/published
  • Required documentation PR: N/A

Header before, light

Header after, light

Header before, dark

Header after, dark

Marketplace before, light

Marketplace after, light

Settings before, dark

Settings after, dark

@berry-13 berry-13 changed the title berry-13/ch-theme-borders 🔇 feat: Let a Theme Quiet Decorative Borders Oct 4, 2026
@codegraph-librechat codegraph-librechat Bot added 🗺️ Theme Engine codegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9) 🛡️ security review labels Oct 4, 2026
@berry-13
berry-13 added this pull request to stack #16746 October 4, 2026 17:08
@berry-13
berry-13 marked this pull request as ready for review October 4, 2026 17:09
Copilot AI balanced review requested due to automatic review settings October 4, 2026 17:09

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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 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-05T20:05:36.030023Z 290972c New commits
🔒 Security Review ✅ Completed 2026-10-04T17:13:00.667406Z e73ec58 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.

@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from e73ec58 to 275e229 Compare October 4, 2026 20:05
@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from 275e229 to 69cc1b3 Compare October 4, 2026 20:52

@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: 69cc1b324a

ℹ️ 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 thread client/src/components/Auth/LoginForm.tsx Outdated
Comment on lines 145 to +147
activeTab === category.value
? 'border-border-heavy bg-surface-active-alt text-text-primary'
: 'border-border-light bg-surface-secondary text-text-secondary hover:bg-surface-hover hover:text-text-primary',
: 'border-border-chrome bg-surface-secondary text-text-secondary hover:bg-surface-hover hover:text-text-primary',

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 Apply chrome alpha to the selected tab border

When the ClickHouse theme is active and a marketplace category is selected, only the inactive branch uses border-border-chrome; the active branch still paints border-border-heavy. As a result, the selected pill retains a visible stroke even though this theme sets chromeBorderAlpha to zero specifically because its basic tabs communicate hover and selection through fill rather than strokes. Route the active border through an alpha-aware chrome role as well while preserving the heavier default-theme appearance.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: the selected pill now draws border-chrome-heavy (border-heavy at the chrome share), so it is unchanged in the bundled themes and quiet in ClickHouse.

Comment thread packages/client/src/theme/themes/clickhouse.ts

@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: fbcfb5ee40

ℹ️ 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".

<span
className={cn(
'border-border-light bg-surface-tertiary text-text-secondary inline-flex max-w-full items-center rounded-full border px-2.5 py-1 text-xs leading-4 font-medium',
'border-border-chrome bg-surface-tertiary text-text-secondary inline-flex max-w-full items-center rounded-full border px-2.5 py-1 text-xs leading-4 font-medium',

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 Preserve the Click UI badge stroke for category badges

When the ClickHouse theme is active, this makes every agent category badge border transparent because chromeBorderAlpha is 0. However, this component already matches Click UI's opaque badge in fill, text, and full radius, and the checked-in Click UI reference explicitly gives that badge a visible click.badge.opaque.color.stroke.default (#e6e7e9 light / #323232 dark), which is the theme's border-light. Keep this badge on border-border-light or introduce a badge-specific role rather than classifying it as borderless chrome.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: Click UI's opaque badge keeps stroke.default, so the category badge is back on border-light.

showBorder: false,
className:
'rounded-full bg-surface-tertiary ring-1 ring-border-light transition-colors duration-150 group-hover:ring-border-medium',
'rounded-full bg-surface-tertiary ring-1 ring-border-chrome transition-colors duration-150 group-hover:ring-border-medium',

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 the avatar hover ring on the chrome role

When a ClickHouse user hovers an agent card, group-hover:ring-border-medium overrides the new ring-border-chrome, so the avatar immediately regains a visible ring despite this theme setting chromeBorderAlpha to zero and the change explicitly migrating the avatar ring to quiet chrome. Use an alpha-aware chrome color for the hover state (or remove that ring state) so interaction does not bypass the theme role.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: the hover ring is border-chrome-medium (border-medium at the chrome share), identical in the bundled themes, so hover no longer bypasses the chrome share.

</TooltipAnchor>
render={
<Button
size="icon"

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 Preserve the multi-conversation button size

When multi-conversation access is enabled, replacing the fixed size-9 control with size="icon" changes this header button to the theme's general button size: 40px in the default theme and 32px in ClickHouse, while the adjacent model, bookmark, share, temporary-chat, and background-task controls remain 36px. The resulting button is visibly misaligned and changes the header layout even though this migration only needs native button behavior and the shared hover treatment; retain the previous 36px size while using the shared primitive.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: the button keeps size-9 on the shared Button, matching the other 36px header controls.

@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from fbcfb5e to 8834f0b Compare October 4, 2026 21:32

@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: 8834f0b50b

ℹ️ 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".

/** Click UI strokes cards, panels, dialogs, fields and tables in stroke.default, but not the
* controls and chat chrome LibreChat outlines (iconButton.*.stroke.default and tabs.basic are
* transparent), and it separates a card's inner regions by fill. */
chromeBorderAlpha: '0', // iconButton.primary.stroke.default

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 Route surface chips through the chrome border role

When the ClickHouse theme is active and a user stages a quote or skill in the composer, client/src/components/Chat/Input/Composer/Chip.tsx renders the shared Chip with tone="surface", but that primitive still hard-codes border-border-light in packages/client/src/components/Chip.tsx. Consequently, setting chromeBorderAlpha to zero here does not quiet these actual shell chips despite the new role explicitly covering chips; migrate the shared surface tone to border-border-chrome rather than only updating feature-local pill implementations.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: the shared Chip surface tone draws border-chrome, so staged quote and skill chips follow the theme role.

Comment on lines +215 to +217
variant: 'outline',
size: ['icon', 'icon-sm', 'icon-xs', 'icon-theme'],
class: 'border-border-chrome',

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 Include subtle icon buttons in the chrome mapping

When the ClickHouse theme is active and the agent version-history panel is opened, its back control renders Button with variant="subtle" and size="icon", but the subtle recipe still uses border-border-light. This compound mapping only covers outline, so that icon button retains a visible stroke even though chromeBorderAlpha is zero; apply the chrome border role to icon-sized subtle buttons as well.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: the icon-sized chrome compound covers the subtle variant too, and IconButton secondary takes the chrome border.

<div className="overflow-hidden" ref={expandRef}>
{shouldRenderBody && (
<div className="border-border-light bg-surface-secondary text-text-secondary relative my-2 rounded-2xl border p-4">
<div className="border-border-inset bg-surface-secondary text-text-secondary relative my-2 rounded-2xl border p-4">

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 outer reasoning cards on the surface border

When the ClickHouse theme is active and a user expands reasoning, this is the card's only outer edge rather than a hairline inside an already-stroked surface, so insetBorderAlpha: 0 removes the entire card stroke even though the theme definition explicitly says Click UI cards remain stroked. Keep this edge on border-border-light; the same outer-card misclassification appears on ThinkingContent in Thinking.tsx.

AGENTS.md reference: AGENTS.md:L144-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 d9e6feb: Reasoning and Thinking cards are the only edge of a card, so they stay on border-light.

@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from d9e6feb to c76cf2f Compare October 4, 2026 22:04

@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: c76cf2fb94

ℹ️ 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".

* controls and chat chrome LibreChat outlines (iconButton.*.stroke.default and tabs.basic are
* transparent), and it separates a card's inner regions by fill. */
chromeBorderAlpha: '0', // iconButton.primary.stroke.default
insetBorderAlpha: '0', // separation by fill, not a nested stroke

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 Route the subagent progress divider through the inset role

When a background task includes an activity digest, SubagentProgress.tsx still renders its top divider with border-border-light, so ClickHouse continues to show that inner stroke even though this new insetBorderAlpha: '0' setting removes the equivalent result and error dividers in BackgroundTaskCard.tsx. Migrate the progress divider to border-border-inset as well so all sections of the same stroked card honor the theme setting consistently.

AGENTS.md reference: AGENTS.md:L144-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 d3def05: the subagent progress divider draws border-border-inset with the other inner card dividers, identical in the bundled themes.

@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from c76cf2f to d3def05 Compare October 4, 2026 22:18
@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from d3def05 to 801001b Compare October 5, 2026 17:55

@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: 801001b8c7

ℹ️ 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".

if (type === 'hunk') {
if (!text) {
return <div className="border-border-light mx-3 my-1.5 border-t" />;
return <div className="border-border-inset mx-3 my-1.5 border-t" />;

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 batched-edit dividers visible

When the ClickHouse theme renders a file-authoring call containing multiple structured edits, buildEditPreviewDiff inserts these empty hunk rows as the only visual boundary between edits, but border-border-inset becomes fully transparent. Consecutive replacements—especially adjacent rows with the same add/delete coloring—then appear to be one edit, obscuring the grouping the divider was created to convey. Keep this semantic separator on border-border-light or introduce a separator-specific role rather than using the quiet inset role.

AGENTS.md reference: AGENTS.md:L144-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 79c5b06: the empty-hunk divider between batched edits is the only boundary between edits, so it stays on border-border-light.

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.

Merged before this was pushed; carried to #16751 in 3da58de (now in 877eb18): the batched-edit divider stays on border-border-light.

@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from 801001b to 6eb84dc Compare October 5, 2026 19:50
Base automatically changed from berry-13/ch-theme-focus-subtle to dev October 5, 2026 20:00
@berry-13
berry-13 force-pushed the berry-13/ch-theme-borders branch from 6eb84dc to 290972c Compare October 5, 2026 20:00
@berry-13
berry-13 merged commit 88eae29 into dev Oct 5, 2026
2 of 15 checks passed
@berry-13
berry-13 deleted the berry-13/ch-theme-borders branch October 5, 2026 20:00

@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: 290972c52f

ℹ️ 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".

'hover:bg-surface-hover flex gap-2.5 px-3 py-2 transition-colors',
snippet ? 'items-start' : 'items-center',
i > 0 && 'border-border-light border-t',
i > 0 && 'border-border-inset border-t',

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 list-row separators on a visible border role

When the ClickHouse theme displays an expanded search with multiple sources, insetBorderAlpha: 0 makes every divider here transparent, so consecutive same-surface links lose their only visual row boundary. These are list separators rather than redundant hairlines between fill-separated card regions—the theme's own reference notes that Click UI retains separators—and the same misclassification affects place-result rows in verticals.tsx and activity rows in EventSubagentActivityGroup.tsx; keep these dividers on border-border-light or add a separator-specific semantic role.

AGENTS.md reference: AGENTS.md:L144-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.

Merged before this was pushed; carried to #16751 in 8ff15f9 (now in 877eb18): the web search source row separators stay on border-border-light.

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

Labels

🛡️ security review 🗺️ Theme Engine 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