From ac0bae760b8ca5ba221156cdb5c801bf5035d5c9 Mon Sep 17 00:00:00 2001 From: knanao Date: Fri, 21 Nov 2025 16:28:17 +0900 Subject: [PATCH 1/2] fix: ensure selected list items are readable with transparent background --- .../cli/cmd/tui/component/prompt/autocomplete.tsx | 6 +++--- .../opencode/src/cli/cmd/tui/context/theme.tsx | 9 +++++++++ .../opencode/src/cli/cmd/tui/ui/dialog-select.tsx | 15 ++++++--------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 3029eafcce3..2f36a1d1a4d 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -5,7 +5,7 @@ import { createMemo, createResource, createEffect, onMount, For, Show } from "so import { createStore } from "solid-js/store" import { useSDK } from "@tui/context/sdk" import { useSync } from "@tui/context/sync" -import { useTheme } from "@tui/context/theme" +import { useTheme, selectedForeground } from "@tui/context/theme" import { SplitBorder } from "@tui/component/border" import { useCommandDialog } from "@tui/component/dialog-command" import { Locale } from "@/util/locale" @@ -471,11 +471,11 @@ export function Autocomplete(props: { backgroundColor={index() === store.selected ? theme.primary : undefined} flexDirection="row" > - + {option.display} - + {option.description} diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 4b7c4de0ae4..54609d2079e 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -86,6 +86,15 @@ type Theme = { syntaxPunctuation: RGBA } +export function selectedForeground(theme: Theme): RGBA { + if (theme.background.a === 0) { + const { r, g, b } = theme.primary + const luminance = 0.299 * r + 0.587 * g + 0.114 * b + return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) + } + return theme.background +} + type HexColor = `#${string}` type RefName = string type Variant = { diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 285c039c11e..aadb7d27092 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -1,5 +1,5 @@ import { InputRenderable, RGBA, ScrollBoxRenderable, TextAttributes } from "@opentui/core" -import { useTheme } from "@tui/context/theme" +import { useTheme, selectedForeground } from "@tui/context/theme" import { entries, filter, flatMap, groupBy, pipe, take } from "remeda" import { batch, createEffect, createMemo, For, Show } from "solid-js" import { createStore } from "solid-js/store" @@ -259,31 +259,28 @@ function Option(props: { onMouseOver?: () => void }) { const { theme } = useTheme() + const fg = selectedForeground(theme) return ( <> - + {Locale.truncate(props.title, 62)} - {props.description} + {props.description} - {props.footer} + {props.footer} From c107e3c376c23bfb812394ae1c0a9d3f5d41dcfc Mon Sep 17 00:00:00 2001 From: knanao Date: Sat, 22 Nov 2025 21:17:03 +0900 Subject: [PATCH 2/2] feat: add backgroundMenu config to make autocomplete list visible with transparent bg --- .../cli/cmd/tui/component/prompt/autocomplete.tsx | 2 +- .../src/cli/cmd/tui/component/prompt/index.tsx | 15 +++++++++++---- .../opencode/src/cli/cmd/tui/context/theme.tsx | 10 +++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 2f36a1d1a4d..8371c395fbe 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -455,7 +455,7 @@ export function Autocomplete(props: { {...SplitBorder} borderColor={theme.border} > - + diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 54609d2079e..ddd13d4425d 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -46,6 +46,7 @@ type Theme = { background: RGBA backgroundPanel: RGBA backgroundElement: RGBA + backgroundMenu: RGBA border: RGBA borderActive: RGBA borderSubtle: RGBA @@ -89,8 +90,8 @@ type Theme = { export function selectedForeground(theme: Theme): RGBA { if (theme.background.a === 0) { const { r, g, b } = theme.primary - const luminance = 0.299 * r + 0.587 * g + 0.114 * b - return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) + const luminance = 0.299 * r + 0.587 * g + 0.114 * b + return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) } return theme.background } @@ -154,11 +155,13 @@ function resolveTheme(theme: ThemeJson, mode: "dark" | "light") { } return resolveColor(c[mode]) } - return Object.fromEntries( + const resolved = Object.fromEntries( Object.entries(theme.theme).map(([key, value]) => { return [key, resolveColor(value)] }), ) as Theme + if (!theme.theme.backgroundMenu) resolved.backgroundMenu = resolved.backgroundElement + return resolved } export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ @@ -300,6 +303,7 @@ function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJs background: bg, backgroundPanel: grays[2], backgroundElement: grays[3], + backgroundMenu: grays[3], // Border colors borderSubtle: grays[6],