Skip to content

tui: fix missing light variants, invisible borders, and token typos in packages/tui #50523

Open

Description

@gotenksIN

Description

Scope Note: This issue covers the TUI themes in packages/tui.
Companion Desktop themes in packages/ui are tracked in #50500.

While checking the built-in TUI themes in packages/tui/src/theme/assets/, we identified missing official light palettes, invisible borders, and token typos:

1. Missing or Broken Light Variants

Several themes have official upstream light variants that are currently missing or broken in the TUI:

  • ayu: Light mode remains dark (#0B0E14). Upstream provides an official Ayu Light palette (#FCFCFC base).
  • nightowl: Light mode remains dark (#011627). Upstream provides an official Light Owl palette (#FBFBFB base).
  • kanagawa: Light mode uses low-contrast dark pastels (< 1.85:1) instead of the official Kanagawa Lotus light theme.
  • catppuccin-frappe: Light mode duplicates dark Frappé colors, and has two hex typos: frappeBlue (#8da4e2 instead of #8caaee) and frappeOverlay2 (#949cb8 instead of #949cbb).

2. Invisible Borders and Token Typos

  • solarized: Panel borders are invisible. border and backgroundPanel share identical values (#073642 in dark mode, #eee8d5 in light mode), producing zero contrast. Setting borders to base01 / base1 restores visibility.
  • material: "darkOrange": "#ffcb6b" duplicates darkYellow. The official Material orange is #f78c6c (currently misplaced in "darkPink").

3. Question for Maintainers: Dark-Only Upstream Themes

Themes such as dracula, monokai, vesper, cobalt2, and matrix do not have official light palettes upstream.
Inverting them naively makes accents unreadable (for example, Vesper success and Dracula yellow drop to near 1:1 contrast).

Would maintainers prefer:

  1. Treating these as dark-only themes (staying dark or falling back to the default theme in light mode)?
  2. Keeping calibrated light inversions with readable contrast?

Steps to Reproduce

  1. Start the TUI (opencode).
  2. Switch theme to Solarized in dark or light mode; observe panel borders are invisible.
  3. Switch theme to Ayu or Night Owl with terminal light mode; observe the theme remains dark.

Activity

  1. github-actions commented on Sep 22, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of (or closely related to) an existing issue filed by the same author. Please check:

    If these are intentionally separate reports (Desktop vs TUI), please clarify that distinction so maintainers can track them independently.

  2. changed the title [-][Bug]: TUI themes: missing official light variants, zero-contrast borders, and palette bugs[/-] [+]tui: fix missing light variants, invisible borders, and token typos in packages/tui[/+] on Sep 22, 2026
  3. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report. I could reproduce the light-mode part of this on 2.2.0 (you didn't give a version, so I used the latest release), and it still happens on the latest dev (fa1260d).

    What I saw in the TUI

    • With theme: { name: "ayu", mode: "light" }, the TUI still renders dark (#0B0E14). The same happens with nightowl (#011627).
    • With the built-in opencode theme, the same mode: "light" setting renders light, so the mode setting itself works.

    Still in the theme files on dev

    • catppuccin-frappe.json: frappeBlue is #8da4e2 and frappeOverlay2 is #949cb8, and light mode reuses the dark Frappé colours.
    • material.json: darkOrange is #ffcb6b, the same as darkYellow.
    • solarized.json: border uses the same value as backgroundPanel (base02 / base2). The screens I captured didn't show a border to compare, so this one is confirmed only from the file.

    I didn't check Kanagawa light mode. The script and recording below show the Ayu case, and the screenshots compare Ayu and Night Owl in light mode with the default theme.

    Your question about dark-only themes is a design choice for the maintainers. Related: #50500 covers the same kind of problems in the Desktop themes (packages/ui).

    recording.mp4

    Screenshot

    Screenshot

    Screenshot

    Reproduction script (drive.ts)
    // Shows built-in TUI theme problems from #50523.
    // THEME / MODE env vars pick the theme (default: solarized / dark).
    import { Effect } from "effect"
    import { OpenCodeDriver } from "opencode-drive"
    
    const name = process.env.THEME ?? "solarized"
    const mode = (process.env.MODE ?? "dark") as "dark" | "light"
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        tuiConfig: { theme: { name, mode } },
        tui: { recording: true, viewport: { cols: 120, rows: 36 } },
      },
      ({ ui }) =>
        Effect.gen(function* () {
          yield* ui.screenshot(`${name}-${mode}-home`)
          // Open the command palette: a panel whose border uses the theme's `border` token.
          yield* ui.press("p", { ctrl: true })
          yield* Effect.sleep("1 second")
          yield* ui.screenshot(`${name}-${mode}-palette`)
          yield* Effect.sleep("1 second")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

  4. gotenksIN commented on Oct 29, 2026

    @gotenksIN
    ContributorAuthor

    Thanks for the detailed report. I could reproduce the light-mode part of this on 2.2.0 (you didn't give a version, so I used the latest release), and it still happens on the latest dev (fa1260d).

    What I saw in the TUI

    • With theme: { name: "ayu", mode: "light" }, the TUI still renders dark (#0B0E14). The same happens with nightowl (#011627).
    • With the built-in opencode theme, the same mode: "light" setting renders light, so the mode setting itself works.

    Still in the theme files on dev

    • catppuccin-frappe.json: frappeBlue is #8da4e2 and frappeOverlay2 is #949cb8, and light mode reuses the dark Frappé colours.
    • material.json: darkOrange is #ffcb6b, the same as darkYellow.
    • solarized.json: border uses the same value as backgroundPanel (base02 / base2). The screens I captured didn't show a border to compare, so this one is confirmed only from the file.

    I didn't check Kanagawa light mode. The script and recording below show the Ayu case, and the screenshots compare Ayu and Night Owl in light mode with the default theme.

    Your question about dark-only themes is a design choice for the maintainers. Related: #50500 covers the same kind of problems in the Desktop themes (packages/ui).

    recording.mp4
    Screenshot

    Screenshot

    Screenshot

    Reproduction script (drive.ts)

    handled in #50525

  5. ffloyd commented on Oct 30, 2026

    @ffloyd

    Still a problem in 2.2.2. At least with ayu theme.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions