Skip to content

feat(native-chat): let users pick chat text and message bubble colors per theme - #25921

Open
pawel-kotowski wants to merge 3 commits into
stablyai:mainfrom
pawel-kotowski:feat/native-chat-text-color
Open

pawel-kotowski wants to merge 3 commits into
stablyai:mainfrom
pawel-kotowski:feat/native-chat-text-color

Conversation

@pawel-kotowski

@pawel-kotowski pawel-kotowski commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

Chat text and your message bubbles have fixed colors. This adds color pickers to the Chat settings page, for the light and the dark theme, so you can choose the color your chat messages are written in and the background of your own messages.

What Changed

  • Settings → Chat → Appearance gets Text color and Your message bubble, each for the light and the dark theme. Each is a color picker plus a hex field. Leaving one empty keeps that theme's normal color, and Reset chat appearance clears them all.
  • The color applies to everything in a message: body text, your own messages, headings, bold, links, inline code, plain code blocks and the message box. Quotes use a 70% version of it. Timestamps and reasoning keep their muted theme color, and syntax-highlighted code keeps its highlighter colors.
  • The bubble color is the background of your messages; their text follows the text color.
  • Mechanism: the colors are saved in nativeChatAppearance as textColorLight / textColorDark / userBubbleColorLight / userBubbleColorDark, one shared key list for normalizing, resolving, resetting and rendering. The chat root publishes them as --chat-text-color-* / --chat-user-bubble-*. In native-chat-appearance.css, the root also captures the theme's own --chat-foreground, --chat-foreground-strong, --chat-code-foreground and --chat-user-surface, and its children set those tokens to the custom color for the current theme (.dark or not), or fall back to the captured theme value. Markdown quotes get their color from --chat-quote-foreground, which is only valid when a custom color is set; otherwise revert-layer keeps the shared renderer's muted quote color.
  • The hex field keeps what you type, so a half-entered value survives the next save; only a valid hex (#abc or #aabbcc, # optional, the same rule as terminal colors) is applied.
  • Both chat renderers read the style from the existing nativeChatAppearanceStyle, so no component changed. The settings search finds both fields (also under "font color").

Why

People who read long agent sessions in chat asked for appearance control over it (#20392). Text color is the smallest piece of that, and a single color can't suit both themes, so there is one per theme.

Overriding the tokens on the root's children rather than the root itself avoids repeating the theme defaults: a custom property can't fall back to its own inherited value, but a child can fall back to a value the root captured. It also composes with the contrast work in #25659, which adjusts the same tokens: a custom color wins, and the theme value (with any contrast applied) is the fallback.

Linked Issue

Part of #20392 (Chat UI appearance settings)

Visual Proof

Before: the Chat page has text size, code size and width only. After: text color and message bubble fields per theme (dark text #e8c48a and dark bubble #2a3442 set; light fields empty, showing their theme colors as placeholders).

A screenshot of a live chat with a custom color will follow.

Testing

  • native-chat-appearance-settings.test.ts: typed colors are kept, empty ones dropped, only valid hex resolves, and Reset clears the colors but keeps fields from newer versions.

  • native-chat-appearance-style.test.ts: a color is published only for the theme that has a valid one.

  • In Electron (Playwright, headless, macOS), on chat markdown laid out like the renderer's output: with a custom color, paragraphs, bold, links, inline code and code blocks compute to it in each theme and quotes to 70% of it. With no color, or only the other theme's color, every element computes exactly to its previous theme color (quotes stay #a1a1a1 dark / #737373 light). The bubble background takes the custom color per theme and otherwise stays at the theme default.

  • pnpm tc, the changed-code quality gate, the localization catalog checks, and the native-chat and settings suites pass.

  • I manually tested these changes locally

  • Automated tests added/updated

AI Disclosure

Implemented with Claude Code (Claude Opus 5.5), reviewed by the author.

Review

Agent skill upstream boundary

  • Not applicable

Notes

  • Cross-platform / SSH / mobile: renderer CSS and a settings field only; no platform, wire or host changes. The web client gets the same setting.
  • Backwards compatibility: two new optional fields in nativeChatAppearance, absent by default; unknown fields from newer versions are still preserved.
  • Performance: two CSS custom properties on the chat root; no extra renders.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (typecheck, changed-file lint and affected suites pass locally; the rest is left to CI)

🤖 Generated with Claude Code

Adds Text color (light theme) and Text color (dark theme) to the Chat settings
page. Each overrides the chat's body and strong text (messages, headings,
links and the message box) in that theme only; empty keeps the theme color.
Faint text, code and tool output keep their theme colors.

The colors are stored as typed so a half-entered hex survives, and only a
valid hex is applied. The chat root publishes --chat-text-color-light/-dark;
its children pick the one for the current theme and fall back to the theme
value the root captures, so no theme default is duplicated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 46ed6ecb-36ac-4863-9ac5-fe2e304ef109

📥 Commits

Reviewing files that changed from the base of the PR and between 91f2571 and 0328196.


📒 Files selected for processing (8)
  • src/renderer/src/components/native-chat/native-chat-appearance-style.test.ts
  • src/renderer/src/components/native-chat/native-chat-appearance-style.ts
  • src/renderer/src/components/native-chat/native-chat-appearance.css
  • src/renderer/src/components/settings/AppearanceChatSection.tsx
  • src/renderer/src/components/settings/chat-appearance-search.ts
  • src/renderer/src/i18n/locales/en.json
  • src/shared/native-chat-appearance-settings.test.ts
  • src/shared/native-chat-appearance-settings.ts

🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/i18n/locales/en.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.



📝 Walkthrough

Walkthrough

Appearance settings now support separate text and user-bubble colors for light and dark themes. The settings interface exposes color controls and search entries for all four settings. Native chat styles apply resolved colors by theme and use captured theme values as fallbacks. Tests cover color normalization, resolution, reset behavior, and exposed style properties.


Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 03281

The change adds per-theme chat text and bubble colors. A user who deliberately picks identical colors can make their own messages unreadable, but they can fix it by editing the field or resetting. No merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 6 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: users can choose chat text and message bubble colors for each theme.
Description check ✅ Passed The description covers the required sections, explains the user-facing changes and rationale, links the issue, and reports testing. It includes a settings screenshot, but does not provide the requeste…

Full details: Docstring Coverage

Explanation

Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 6 files. (2 skipped: 2 unsupported.)


  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

pawel-kotowski and others added 2 commits October 6, 2026 19:11
…quotes

Inline code and plain code blocks read --chat-code-foreground and quotes use
the shared renderer's muted color, so they kept the theme color after a custom
text color was set. Code now takes the custom color and quotes a 70% version
of it; without a custom color both keep their theme colors. Syntax-highlighted
code keeps its highlighter theme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds Your message bubble (light theme) and (dark theme) to the Chat settings
page, applied through --chat-user-surface with the same per-theme fallback as
the text color. The four chat color settings now share one key list for
normalizing, resolving, resetting and rendering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pawel-kotowski pawel-kotowski changed the title feat(native-chat): let users pick the chat text color per theme feat(native-chat): let users pick chat text and message bubble colors per theme Oct 6, 2026
@pawel-kotowski
pawel-kotowski force-pushed the feat/native-chat-text-color branch from 0328196 to 767b236 Compare October 12, 2026 11:18

This branch has not been deployed

No deployments
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.

1 participant