Skip to content

Commit 1fd0058

Browse files
authored
fix(tui): ensure fatal error UI is readable in light mode (anomalyco#5387)
1 parent 61ba844 commit 1fd0058

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

  • packages/opencode/src/cli/cmd/tui

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ export function tui(input: { url: string; args: Args; onExit?: () => Promise<voi
107107
render(
108108
() => {
109109
return (
110-
<ErrorBoundary fallback={(error, reset) => <ErrorComponent error={error} reset={reset} onExit={onExit} />}>
110+
<ErrorBoundary
111+
fallback={(error, reset) => <ErrorComponent error={error} reset={reset} onExit={onExit} mode={mode} />}
112+
>
111113
<ArgsProvider {...input.args}>
112114
<ExitProvider onExit={onExit}>
113115
<KVProvider>
@@ -536,7 +538,12 @@ function App() {
536538
)
537539
}
538540

539-
function ErrorComponent(props: { error: Error; reset: () => void; onExit: () => Promise<void> }) {
541+
function ErrorComponent(props: {
542+
error: Error
543+
reset: () => void
544+
onExit: () => Promise<void>
545+
mode?: "dark" | "light"
546+
}) {
540547
const term = useTerminalDimensions()
541548
useKeyboard((evt) => {
542549
if (evt.ctrl && evt.name === "c") {
@@ -547,6 +554,15 @@ function ErrorComponent(props: { error: Error; reset: () => void; onExit: () =>
547554

548555
const issueURL = new URL("https://github.com/sst/opencode/issues/new?template=bug-report.yml")
549556

557+
// Choose safe fallback colors per mode since theme context may not be available
558+
const isLight = props.mode === "light"
559+
const colors = {
560+
bg: isLight ? "#ffffff" : "#0a0a0a",
561+
text: isLight ? "#1a1a1a" : "#eeeeee",
562+
muted: isLight ? "#8a8a8a" : "#808080",
563+
primary: isLight ? "#3b7dd8" : "#fab283",
564+
}
565+
550566
if (props.error.message) {
551567
issueURL.searchParams.set("title", `opentui: fatal: ${props.error.message}`)
552568
}
@@ -567,27 +583,31 @@ function ErrorComponent(props: { error: Error; reset: () => void; onExit: () =>
567583
}
568584

569585
return (
570-
<box flexDirection="column" gap={1}>
586+
<box flexDirection="column" gap={1} backgroundColor={colors.bg}>
571587
<box flexDirection="row" gap={1} alignItems="center">
572-
<text attributes={TextAttributes.BOLD}>Please report an issue.</text>
573-
<box onMouseUp={copyIssueURL} backgroundColor="#565f89" padding={1}>
574-
<text attributes={TextAttributes.BOLD}>Copy issue URL (exception info pre-filled)</text>
588+
<text attributes={TextAttributes.BOLD} fg={colors.text}>
589+
Please report an issue.
590+
</text>
591+
<box onMouseUp={copyIssueURL} backgroundColor={colors.primary} padding={1}>
592+
<text attributes={TextAttributes.BOLD} fg={colors.bg}>
593+
Copy issue URL (exception info pre-filled)
594+
</text>
575595
</box>
576-
{copied() && <text>Successfully copied</text>}
596+
{copied() && <text fg={colors.muted}>Successfully copied</text>}
577597
</box>
578598
<box flexDirection="row" gap={2} alignItems="center">
579-
<text>A fatal error occurred!</text>
580-
<box onMouseUp={props.reset} backgroundColor="#565f89" padding={1}>
581-
<text>Reset TUI</text>
599+
<text fg={colors.text}>A fatal error occurred!</text>
600+
<box onMouseUp={props.reset} backgroundColor={colors.primary} padding={1}>
601+
<text fg={colors.bg}>Reset TUI</text>
582602
</box>
583-
<box onMouseUp={props.onExit} backgroundColor="#565f89" padding={1}>
584-
<text>Exit</text>
603+
<box onMouseUp={props.onExit} backgroundColor={colors.primary} padding={1}>
604+
<text fg={colors.bg}>Exit</text>
585605
</box>
586606
</box>
587607
<scrollbox height={Math.floor(term().height * 0.7)}>
588-
<text>{props.error.stack}</text>
608+
<text fg={colors.muted}>{props.error.stack}</text>
589609
</scrollbox>
590-
<text>{props.error.message}</text>
610+
<text fg={colors.text}>{props.error.message}</text>
591611
</box>
592612
)
593613
}

0 commit comments

Comments
 (0)