Repository navigation
Description
Bug Description
When using a light theme on a terminal with a white/light background, text inside code blocks (especially those without a language annotation) is rendered as white text on a white background, making it completely invisible. This cannot be fixed through the theme JSON — the white color is hardcoded in the rendering layer.
This issue was originally filed at anomalyco/opencode#18353 but the root cause is in opentui.
Steps to Reproduce
- Use a terminal with a white/light background
- Use a custom theme (in an OpenCode context) with all dark foreground colors:
{ "theme": { "text": "#383A42", "markdownCodeBlock": "#383A42", "syntaxComment": "#5F6169", "syntaxKeyword": "#A626A4", ... } } - Render markdown containing a code block without a language annotation (bare
```or indented text) - The text inside the code block is rendered in white — invisible on the light background
Root Cause Analysis
Three contributing factors were identified:
1. Hardcoded white default foreground in TextBufferRenderable
The default foreground color is hardcoded to white:
// TextBufferRenderable.ts
protected _defaultOptions = {
fg: RGBA.fromValues(1, 1, 1, 1), // WHITE
bg: RGBA.fromValues(0, 0, 0, 0), // transparent
...
}2. createCodeRenderable() does not pass fg from the theme
When MarkdownRenderable creates a CodeRenderable for fenced code blocks, it passes syntaxStyle but not fg:
// Markdown.ts
private createCodeRenderable(token: Tokens.Code, id: string, marginBottom: number = 0): Renderable {
return new CodeRenderable(this.ctx, {
id,
content: token.text,
filetype: token.lang || undefined,
syntaxStyle: this._syntaxStyle, // syntax style IS passed
conceal: this._concealCode,
// ... NO fg prop!
})
}This means the code block falls back to the hardcoded white default for any text not covered by syntax highlighting.
3. markdownCodeBlock theme property is effectively unused
In the OpenCode integration, the markdownCodeBlock property is accepted in the theme JSON schema but is never mapped to any tree-sitter scope in getSyntaxRules(). Setting it has no effect on rendering.
Combined effect
- For code blocks with a recognized language: the
"default"syntax scope (mapped totheme.text) colors unrecognized tokens correctly, but there may be a flash of white before highlighting completes - For code blocks without a language annotation: the entire block renders in the hardcoded white default, with no way to override it via the theme
Suggested Fix
- Pass
fgtoCodeRenderable: IncreateCodeRenderable(), passfgfrom the theme's text color (or from the resolved"default"syntax rule) - Make the default foreground theme-aware: Consider changing
TextBufferRenderable's defaultfgfrom hardcoded white to a value derived from the theme or the terminal's default foreground
Environment
- Terminal: white/light background
- OS: macOS
- Context: OpenCode TUI with a custom light theme
Activity
fix(core): pass theme default fg/bg to code block renderables
simonklee commentedon Mar 20, 2026
157193a