[Bug]: Maximum appearance contrast still renders assistant replies at 80% opacity
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
Summary
Assistant reply paragraphs remain gray in dark mode even when Settings > Appearance > Contrast is set to its maximum, 200%. The setting brightens the foreground color, but ChatMarkdown then applies a fixed 80% color alpha. Users therefore cannot reach fully opaque reply text through the existing control.
At maximum contrast, the foreground reaches white, but ordinary reply text still has alpha 0.8. The slider works; the reply-specific multiplier limits its result.
The chat-specific contrast PR #7395 was closed because #7906 had shipped. This report isolates the remaining alpha limit after that change.
Before submitting
- I searched existing issues and PRs. Related reports and their resolution are linked below; I found no open issue specifically tracking the remaining reply-text alpha limit.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web, also used by the desktop app.
Steps to reproduce
Use the built-in T3 Code dark theme and the following assistant-message Markdown in a conversation or renderer fixture:
## Contrast check
This paragraph should be comfortable to read.
- This list item uses ordinary reply text.
<details>
<summary>More text</summary>
This expanded paragraph should follow the same text contrast setting.
</details>
- Set Settings > Appearance > Contrast to 100%.
- Compare the heading, paragraph, and list item in that same reply.
- Set Contrast to its maximum, 200%, and compare the same content again.
- Inspect the paragraph's computed
color, including its alpha. Inspecting the CSSopacityproperty alone will miss this. - Expand More text and inspect its paragraph too.
Source-derived result at 200%:
| Text | Foreground before reply styling | Final color alpha |
|---|---|---|
| Heading | White | 1 |
| Ordinary paragraph / list | White | 0.8 |
| Expanded details paragraph | White | 0.8 |
The dim appearance was observed in the installed desktop app. The table and reproduction recipe follow from the verified source and installed CSS; a fresh 100%/200% UI comparison has not been captured for this report.
Expected behavior
The available contrast controls should let users reach fully opaque assistant body text. Long replies should be able to use the same full-strength foreground as other primary text.
This is the requested outcome; whether it belongs in the existing control or a scoped control is a product decision. An opt-in solution can preserve the current default.
Actual behavior and cause
Verified against upstream commit 211618fd9fe39d3dde01171a6856ce9f633571c9:
- appearanceContrast.ts maps 200% to a 100% base and 100% contrast boost.
- index.css uses that boost to move
--contrast-foregroundto the target color, white in dark mode. - The ChatMarkdown root still uses
text-foreground/80. The installed stylesheet implements this as:
color: color-mix(in oklab, var(--contrast-foreground) 80%, transparent);
Consequently, even an opaque white foreground becomes white with alpha 0.8. Over a #0a0a0a canvas, that composites to approximately #cecece, not white. This is a calculated result from the CSS, not a sampled screenshot value.
This is color alpha, not the element's CSS opacity property. Raising the global contrast or setting the theme text color to white does not remove the multiplier.
The expanded details body independently uses the same class, so changing only the root would leave that path dim. Headings already use the full foreground.
Impact
Cosmetic/readability issue. Long assistant responses are noticeably harder to read, and the existing setting cannot produce the desired full-strength text.
Version and environment
- T3 Code desktop 0.0.40 on macOS; packaged commit
09e8de9c655a. - The root class and generated CSS were checked in the installed bundle.
- The same root/details classes and contrast calculation remain in upstream at the commit linked above.
- The renderer is shared by web and desktop; this is independent of model output. Mobile's native renderer was not inspected.
Related work
- #7395 directly addressed reply-text alpha and includes public before/after examples. It was closed unmerged in favor of #7906.
- #7906 shipped the global contrast control, but leaves the reply-specific multiplier in place.
- #233 and #2718 are closed broader contrast reports. This report isolates the remaining behavior in the shipped control.
Verification for a fix
- A supported setting can produce alpha 1 for ordinary reply paragraphs, lists, and expanded details.
- Compare the same fixture at 100% and 200%, recording computed colors or screenshots. Verify the resulting body-text alpha, rather than only the setting value or root CSS variable.
- Verify both light and dark themes; use theme-appropriate foregrounds.
- Preserve the default appearance if the fix is opt-in, and keep syntax highlighting and secondary UI text scoped to their existing roles.
Workaround
Removing the reply-specific /80 class or overriding its text color can bypass the limit locally, but no supported appearance setting currently removes it. No installed-app modification was made for this report.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in apps/web/src/components/ChatMarkdown.tsx at the ChatMarkdown root and expanded details body, then review the contrast mapping in apps/web/src/appearanceContrast.ts and the related rules in apps/web/src/index.css. Reproduce the supplied Markdown fixture at 100% and 200% contrast, checking computed color alpha for paragraphs, lists, and expanded details in both themes; done means supported settings can reach alpha 1 without changing default or secondary text styling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- accessibility, frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100