Skip to content

text_view: Follow the container's text color so rich text reads in filled bubbles - #3329

Open
Bombatomica64 wants to merge 2 commits into
longbridge:mainfrom
Bombatomica64:fix/bubble-textview-color
Open

Bombatomica64 wants to merge 2 commits into
longbridge:mainfrom
Bombatomica64:fix/bubble-textview-color

Conversation

@Bombatomica64

@Bombatomica64 Bombatomica64 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3326

Description

TextView paints its own text color on its root, so it does not inherit the color a Bubble sets on its content. In a Filled bubble, Markdown is drawn in the theme foreground on the primary surface: white on white in dark mode. Links (primary) disappear too, and code backgrounds (accent/muted) are tuned for the page, not for a primary surface.

The first revision added BubbleVariant::text_view_style(cx), which callers passed to every TextView in a bubble. That repeated the bubble's variant at each call site and would have needed the same method on every other colored container, so the fix now lives in TextView itself:

  • Follow the container's text color. A TextView without an explicit .style() takes the text color its container sets (window.text_style().color, or its own .text_color()).
  • Same-polarity surfaces (Secondary, Destructive, a popover): only the body text changes. Links, code and borders keep the theme colors.
  • Inverted surfaces (Filled, whose primary fill is dark on a light page and light on a dark one): when the inherited color is more than 0.6 away from the style's foreground in Oklab lightness, links, muted text (block quotes), code and inline-code backgrounds, borders, selection, the table header and body backgrounds are all derived from it. The dark flag flips, so todo checkboxes pick the right icon. The installed syntax highlighter is left out, since its colors are made for the page.
  • Opt-in in Base, on in Component. TextViewDefaults::with_inherit_text_color(true) enables it. Component turns it on because its Root sets the theme foreground. A Base-only window that sets no root text color would otherwise inherit GPUI's default black.

Bubble needs no change, since it already sets each variant's text color.

Screenshot

Filled, Secondary and Destructive bubbles with a link, inline code, a block quote, a todo list, a fenced code block and a table, in the light and dark themes, read correctly. Before this change, the Filled bubble's text, link and table were invisible in dark mode.

Public API

gpui-base

  • gpui_base::TextViewDefaults::with_inherit_text_color(self, inherit: bool) -> Self: makes text views without an explicit style follow the text color their container sets, adapting every color on an inverted surface.
  • gpui_base::TextViewDefaults::inherit_text_color(&self) -> bool: whether that is enabled.

gpui-component

No items are added. Text views now follow the container's text color by default, because Component installs with_inherit_text_color(true).

How to Test

  • cargo test -p gpui-base -p gpui-component
    • text_color_of_a_matching_surface_only_replaces_the_body_text and text_color_of_an_inverted_surface_derives_every_color_from_it cover the color derivation in both themes.
    • text_view_follows_the_text_color_of_its_container checks that a view under a container with primary_foreground text resolves to that color with a flipped dark flag, and that an explicit .style() still wins.
  • Manually: render Bubble::new().child(TextView::markdown("reply", text)) with links, code, quotes, todos and a table in each variant, and toggle the theme.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes.
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific) (not platform-specific)

🤖 Generated with Claude Code

TextView paints its own text color, so a TextView inside a Filled bubble
drew the theme foreground on the primary surface (white on white in dark
mode), with primary links and accent code backgrounds equally hidden.

BubbleVariant::text_view_style returns a TextViewStyle whose text color
matches the bubble; for Filled it also derives link and code colors from
the text color. The per-variant text color now lives in one place and is
used by both the bubble surface and the style.

Closes longbridge#3326

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 07:42

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.

@Bombatomica64

Bombatomica64 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

I've added before/after screen recordings to the Screenshot section (Android, dark theme, Kit 0.7.0 with and without this diff).

Before

pr3329-before.mp4

After

pr3329-after.mp4

…::text_view_style

Replace the per-variant `BubbleVariant::text_view_style` with inheritance in
`TextView`: a view without an explicit style takes the text color its
container sets. On a surface inverted from the page, such as a `Filled`
bubble, links, muted text, code and table backgrounds, borders and selection
are derived from that color too, the dark flag flips, and the installed
syntax highlighter is left out.

`TextViewDefaults::with_inherit_text_color` turns this on; Component enables
it because its Root sets the theme foreground.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@huacnlee huacnlee changed the title bubble: Add BubbleVariant::text_view_style for readable rich text text_view: Follow the container's text color so rich text reads in filled bubbles Oct 1, 2026
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.

Bubble: TextView inside a Filled bubble ignores the bubble text color (white on white in dark mode)

4 participants