dark-ansi theme: expanded message background (userMessageBackgroundHover) collides with subtle/inactive text on color7, making expanded tool calls unreadable in fullscreen

Status Open
Reported on v2.1.207
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 13, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Summary

In fullscreen rendering mode, the dark-ansi theme maps the expanded message background and the dimmed text colors to the same ANSI slot (color7). Expanding a message (e.g. clicking a Bash tool call) therefore renders text on a background of an identical or near-identical color, making the expanded content unreadable.

This is the same class of bug as #40905 (which concluded "Dark mode correctly separates concerns"). That is no longer true now that the fullscreen background tokens exist.

Root cause

The dark-ansi preset defines:

| Token | Value | Role |
|---|---|---|
| userMessageBackgroundHover | ansi:white (color7) | background behind a hovered or expanded message |
| subtle | ansi:white (color7) | faint borders, de-emphasized secondary text |
| inactive | ansi:white (color7) | hints, timestamps, disabled items |
| text | ansi:whiteBright (color15) | default foreground text |
| selectionBg | ansi:blue | mouse selection background |

userMessageBackgroundHover collides with subtle and inactive on color7. Because both sides resolve to the same ANSI slot, the collision is palette-independent — it reproduces on any terminal color scheme, since no palette can make color7 contrast with color7.

text (color15) sits on userMessageBackgroundHover (color7). In every conventional palette color15 and color7 are both light, so this pair is also very low contrast.

Confirmed against the shipped binary (v2.1.207). The expanded state is driven directly by this token:

backgroundColor: expanded ? "userMessageBackgroundHover" : void 0

Concrete numbers (Base16 Eighties palette)

  • color7 = #D3D0C8, color15 = #F2F0EC
  • Expanded background: #D3D0C8
  • subtle / inactive text: #D3D0C8 → contrast 1.0:1 (literally the same color)
  • text: #F2F0EC on #D3D0C8 → contrast 1.15:1

WCAG AA requires 4.5:1.

Because selectionBg is ansi:blue, dragging the mouse over the region repaints the background and the text becomes readable — a useful confirmation of the diagnosis, and the only current workaround without changing themes.

Reproduce

  1. /themeDark mode (ANSI colors only)
  2. /tui fullscreen (or set CLAUDE_CODE_NO_FLICKER=1)
  3. Run any Bash tool call
  4. Click the tool call in the transcript to expand it
  5. The expanded detail region renders light-on-light and is unreadable

Expected

Background tokens and foreground tokens should never resolve to the same ANSI slot. dark-ansi should draw its fullscreen backgrounds from the dark end of the palette, mirroring how it already separates text (color15) from userMessageBackground (color8).

Suggested minimal fix — reassign the collided token:

userMessageBackgroundHover:  ansi:white  →  ansi:black   (color0)

…paired with a distinct value for bashMessageBackgroundColor, which currently already uses ansi:black, so that hovering a Bash entry still produces a visible state change. More generally, all six fullscreen tokens (userMessageBackground, userMessageBackgroundHover, messageActionsBackground, bashMessageBackgroundColor, memoryBackgroundColor, selectionBg) should be constrained to background-appropriate slots (color0 / color8) in dark-ansi, and to color7 / color15 in light-ansi.

Workaround

A custom theme overriding only the fullscreen tokens restores readability (requires ≥ v2.1.118):

// ~/.claude/themes/dark-ansi-fullscreen-fix.json
{
  "name": "Dark ANSI (fullscreen-safe)",
  "base": "dark-ansi",
  "overrides": {
    "userMessageBackground":      "#2D2D2D",
    "userMessageBackgroundHover": "#3F3F3D",
    "messageActionsBackground":   "#4A4A48",
    "bashMessageBackgroundColor": "#242424",
    "memoryBackgroundColor":      "#2D2D2D",
    "selectionBg":                "#515151"
  }
}

This sacrifices the palette-following property that is the entire point of an ANSI theme, so it is a mitigation rather than a fix.

Environment

  • Claude Code 2.1.207 (native binary, linux)
  • Theme: dark-ansi
  • tui: "fullscreen"
  • Windows Terminal → WSL2 (Ubuntu 22.04) → tmux
  • TERM=tmux-256color, tmux Tc capability true
  • Terminal color scheme: Base16 Eighties (bug is palette-independent — any scheme reproduces it)

View original on GitHub ↗

3 Comments

rus-yurchenko · 26 days ago

Confirmed still present in 2.1.221, and I have two refinements to the suggested fix.

1. userMessageBackgroundHover: ansi:black collides with bashMessageBackgroundColor.

You flag this in the issue already, but it's worse than a cosmetic pairing problem — it's unfixable within the 16-color palette. Dumping the shipped dark-ansi preset from 2.1.221:

userMessageBackground:       ansi:blackBright   (color8)
bashMessageBackgroundColor:  ansi:black         (color0)
memoryBackgroundColor:       ansi:blackBright   (color8)
composerSidebarBackground:   ansi:blackBright   (color8)

dark-ansi needs three mutually-distinguishable dark backgrounds (normal message, hovered/expanded message, bash message) but ANSI offers only two dark slots, and both are already claimed. So reassigning the collided token to ansi:black trades an unreadable state for an invisible one: hovering a Bash entry becomes a no-op. There is no third ANSI slot to move it to.

2. ansi256(N) is accepted by the custom-theme validator and resolves the scarcity.

The override validator accepts four value forms:

rgb(r, g, b)  |  #RRGGBB / #RGB  |  ansi256(N)  |  ansi:<name>

The xterm 256-cube grayscale ramp (232–255) is conventionally left unremapped by terminals, so it supplies a dark background without consuming one of the 16 palette slots the theme is built around. That makes a single-token fix sufficient:

{
  "name": "Dark ANSI (fullscreen-safe)",
  "base": "dark-ansi",
  "overrides": { "userMessageBackgroundHover": "ansi256(238)" }
}

subtle/inactive (color7) and text (color15) now sit on a dark gray, and hover remains a visible state change against both color8 and color0.

On the six-token workaround in the issue body: it does restore readability, but overriding userMessageBackground with absolute hex makes the user's own messages stop tracking the terminal palette — which is the whole point of choosing an -ansi theme. Only userMessageBackgroundHover is actually collided; the other five tokens in that snippet are already background-appropriate (color0/color8/ansi:blue) and are better left as palette references.

So for the upstream fix, I'd suggest dark-ansi draw its fullscreen backgrounds from the 256 grayscale ramp rather than trying to fit three backgrounds into two ANSI slots.

Minor note for anyone debugging their own override file: the merge step requires both that the token name exists on the base theme and that the value passes validation, and silently drops anything failing either check. A typo'd token name and an unsupported value are indistinguishable from "the feature doesn't work."

squattingmonk · 13 days ago

Confirming this reproduces outside fullscreen mode and WSL too — plain scrolling mode, Linux (Arch), kitty terminal, no tmux.

Trigger: create a new file with the Write tool, then click + to expand it in the transcript. Same collision: with a custom Nord-based dark-ansi theme (and even on the unmodified stock dark-ansi preset, no customization at all), the expanded content's background and text both resolve to ansi:white (color7), rendering as solid, unreadable color regardless of what the terminal maps color7 to.

I verified this is palette-independent exactly as described here: I set my terminal's color7 to an arbitrary debug color (bright orange) and both the background and the text of the expanded content rendered in that same orange — confirming both sides really do resolve to the identical ANSI slot, not just a low-contrast pair.

The proposed ansi256(N) grayscale-ramp workaround in the comment above looks like the right fix — will try userMessageBackgroundHover: ansi256(238) (or similar) as a custom-theme override and report back if it also resolves the "expand created file" case, since that may be a distinct token from the Bash-tool-call hover case described in the issue body.

Update: Confirmed. Overriding only userMessageBackgroundHover to ansi256(238) (leaving subtle/inactive/text as their stock ansi:white/ansi:whiteBright values) fixes the "expand created file" case too — same token, same fix, no distinct code path. Full readable diff: soft gray background, white text, and diff colors (diffAdded/diffRemoved etc., which are untouched by this override) stayed correctly muted throughout. So the fix proposed above resolves both triggers with the single-token change.

(Note: this comment's text, including this update, was drafted by Claude Code on behalf of the reporter.)

bcherny collaborator · 10 days ago

Confirmed / reproduced on 2.1.233 (Linux). We inspected the theme tables in the shipped 2.1.233 build and they match your analysis exactly: in the dark ANSI theme, the expanded-message background and the subtle/inactive text colors all resolve to the same ANSI slot (color7), and the default text color (color15) sits on color7 as well. Since no terminal palette can make a color contrast with itself, expanded tool calls in fullscreen are unreadable in this theme regardless of color scheme — your 1.0:1 / 1.15:1 numbers check out.

This is a real bug in the theme's fullscreen background token assignments, not a regression in your setup, and your custom-theme override is the right workaround for now (as is mouse-selecting the text). Fixing it means drawing the dark ANSI theme's backgrounds from the dark end of the 16-color palette while keeping the expanded state visually distinct from the normal message background — we're looking at the right assignment within those constraints.

Thanks for the precise report — the palette-independence argument and the Base16 numbers made this verifiable in minutes.

🤖 Generated with Claude Code