Skip to content

Code blocks use hardcoded white foreground, making text invisible on light backgrounds #836

Closed

Description

@yykamei

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

  1. Use a terminal with a white/light background
  2. Use a custom theme (in an OpenCode context) with all dark foreground colors:
    {
      "theme": {
        "text": "#383A42",
        "markdownCodeBlock": "#383A42",
        "syntaxComment": "#5F6169",
        "syntaxKeyword": "#A626A4",
        ...
      }
    }
  3. Render markdown containing a code block without a language annotation (bare ``` or indented text)
  4. 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 to theme.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

  1. Pass fg to CodeRenderable: In createCodeRenderable(), pass fg from the theme's text color (or from the resolved "default" syntax rule)
  2. Make the default foreground theme-aware: Consider changing TextBufferRenderable's default fg from 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

  1. added a commit that references this issue on Mar 20, 2026
    4751558
  2. simonklee commented on Mar 20, 2026

    @simonklee
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions