summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKoichi Nakayamada <[email protected]>2025-12-11 14:39:27 -0800
committerGitHub <[email protected]>2025-12-11 16:39:27 -0600
commit1fd005838c90b987f64d1f3bf047d7c39db3acab (patch)
tree18eb1120c9c1bb4257347f2e200ecff22fa617bb
parent61ba844234c86eac15537229c7de2b1d8cc3984f (diff)
downloadopencode-1fd005838c90b987f64d1f3bf047d7c39db3acab.tar.gz
opencode-1fd005838c90b987f64d1f3bf047d7c39db3acab.zip
fix(tui): ensure fatal error UI is readable in light mode (#5387)
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx48
1 files changed, 34 insertions, 14 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index 16544d008..28e841122 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -107,7 +107,9 @@ export function tui(input: { url: string; args: Args; onExit?: () => Promise<voi
render(
() => {
return (
- <ErrorBoundary fallback={(error, reset) => <ErrorComponent error={error} reset={reset} onExit={onExit} />}>
+ <ErrorBoundary
+ fallback={(error, reset) => <ErrorComponent error={error} reset={reset} onExit={onExit} mode={mode} />}
+ >
<ArgsProvider {...input.args}>
<ExitProvider onExit={onExit}>
<KVProvider>
@@ -536,7 +538,12 @@ function App() {
)
}
-function ErrorComponent(props: { error: Error; reset: () => void; onExit: () => Promise<void> }) {
+function ErrorComponent(props: {
+ error: Error
+ reset: () => void
+ onExit: () => Promise<void>
+ mode?: "dark" | "light"
+}) {
const term = useTerminalDimensions()
useKeyboard((evt) => {
if (evt.ctrl && evt.name === "c") {
@@ -547,6 +554,15 @@ function ErrorComponent(props: { error: Error; reset: () => void; onExit: () =>
const issueURL = new URL("https://github.com/sst/opencode/issues/new?template=bug-report.yml")
+ // Choose safe fallback colors per mode since theme context may not be available
+ const isLight = props.mode === "light"
+ const colors = {
+ bg: isLight ? "#ffffff" : "#0a0a0a",
+ text: isLight ? "#1a1a1a" : "#eeeeee",
+ muted: isLight ? "#8a8a8a" : "#808080",
+ primary: isLight ? "#3b7dd8" : "#fab283",
+ }
+
if (props.error.message) {
issueURL.searchParams.set("title", `opentui: fatal: ${props.error.message}`)
}
@@ -567,27 +583,31 @@ function ErrorComponent(props: { error: Error; reset: () => void; onExit: () =>
}
return (
- <box flexDirection="column" gap={1}>
+ <box flexDirection="column" gap={1} backgroundColor={colors.bg}>
<box flexDirection="row" gap={1} alignItems="center">
- <text attributes={TextAttributes.BOLD}>Please report an issue.</text>
- <box onMouseUp={copyIssueURL} backgroundColor="#565f89" padding={1}>
- <text attributes={TextAttributes.BOLD}>Copy issue URL (exception info pre-filled)</text>
+ <text attributes={TextAttributes.BOLD} fg={colors.text}>
+ Please report an issue.
+ </text>
+ <box onMouseUp={copyIssueURL} backgroundColor={colors.primary} padding={1}>
+ <text attributes={TextAttributes.BOLD} fg={colors.bg}>
+ Copy issue URL (exception info pre-filled)
+ </text>
</box>
- {copied() && <text>Successfully copied</text>}
+ {copied() && <text fg={colors.muted}>Successfully copied</text>}
</box>
<box flexDirection="row" gap={2} alignItems="center">
- <text>A fatal error occurred!</text>
- <box onMouseUp={props.reset} backgroundColor="#565f89" padding={1}>
- <text>Reset TUI</text>
+ <text fg={colors.text}>A fatal error occurred!</text>
+ <box onMouseUp={props.reset} backgroundColor={colors.primary} padding={1}>
+ <text fg={colors.bg}>Reset TUI</text>
</box>
- <box onMouseUp={props.onExit} backgroundColor="#565f89" padding={1}>
- <text>Exit</text>
+ <box onMouseUp={props.onExit} backgroundColor={colors.primary} padding={1}>
+ <text fg={colors.bg}>Exit</text>
</box>
</box>
<scrollbox height={Math.floor(term().height * 0.7)}>
- <text>{props.error.stack}</text>
+ <text fg={colors.muted}>{props.error.stack}</text>
</scrollbox>
- <text>{props.error.message}</text>
+ <text fg={colors.text}>{props.error.message}</text>
</box>
)
}