Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ file is the human-readable summary of what changed and why.
the separation), and the status footer now sits on the terminal's last row
instead of two rows above it.

- **Visible selection in the question panel** — the highlighted answer (and the
hovered question tab) used a background one shade off the panel, which was
effectively invisible in light themes; the highlight is now derived from the
panel and text colors so it reads in both light and dark.

- **No stray line on tool output** — expanded tool-output panels (bash output,
generic tool results) no longer draw a background-colored left border glyph,
which showed up as an odd thin vertical line along the panel's left edge on
Expand Down
1 change: 1 addition & 0 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ from the squash message first, or use a plain merge.
| `packages/tui/src/component/spinner.tsx` | `SPINNER_FRAMES` swapped from cli-spinners "dots" (10 braille frames) to cli-spinners "sand" (35 braille frames, falling-sand animation); interval stays 80 ms | Fork visual identity for the shared `Spinner` component (in-progress tool/thinking rows, startup loading, session-list dialogs). | Keep our frames array; take upstream's surrounding changes. |
| `packages/tui/src/component/prompt/index.tsx` | Busy footer spinner is cli-spinners "aesthetic" instead of the Knight Rider block scanner: module-level `FOOTER_FRAMES` (`▰▱` ramp, 7 chars, 8 frames), `spinnerDef` keeps the agent-color resolution but returns those frames plus a per-char color fn (`▰` → agent color, `▱` → `deriveInactiveColor(color, 0.3)`) instead of `createFrames`/`createColors` from `ui/spinner`, and the `<spinner>` interval is 120 ms (was 40; cli-spinners' stock 80 felt too fast). `ui/spinner.ts` itself is untouched; only its `deriveInactiveColor` import remains. | Fork visual identity for the busy indicator next to `esc interrupt`; the agent accent color still drives it. | Keep `FOOTER_FRAMES`, our `spinnerDef` body, the `deriveInactiveColor` import, and the 120 ms interval; take upstream's surrounding changes. If upstream reworks `spinnerDef`, re-apply the aesthetic frames + per-char color fn on top. |
| `packages/tui/src/component/prompt/index.tsx`, `packages/tui/src/routes/session/index.tsx` | Compact prompt/footer spacing: the input box's interior `paddingTop={1}` is replaced by a height-1 half-block top-edge row above the box (`border={["top"]}`, `horizontal: "▄"` when `backgroundElement` is opaque, `" "` otherwise — mirror of the existing `"▀"` bottom-edge row; the agent/model meta row keeps its `paddingTop={1}`), and the session content container loses its `paddingBottom={1}` and its `gap={1}` (the gap fired between every pair of children — transcript↔prompt, and prompt↔the trailing flexGrow spacer, where it left a phantom blank row under the footer even at zero spacer height; the half-block lip is now the only transcript↔prompt separation) so the prompt footer line sits on the terminal's last row | The prompt box was a row taller than its content needed, a full blank row sat between the transcript and the box, and the footer floated 2 rows above the bottom edge; the half-block lip keeps a visible box edge above the text at half the height. | Keep the top-edge lip row and the padding/gap removals; take upstream's surrounding changes. If upstream restyles the box edges, re-apply the symmetric half-block lips and keep the container un-padded. |
| `packages/tui/src/routes/session/question.tsx` | Selection/hover highlight color: a `highlight` memo (`tint(theme.backgroundPanel, theme.text, 0.1)`) replaces `theme.backgroundElement` on the active option row (number + label boxes, both the option list and the "Type your own answer" row) and on the question/Confirm tab hover state | `backgroundElement` sits ~1.04x off `backgroundPanel` in light themes (`#f5f5f5` on `#fafafa` for `codev`), so the selected answer had no visible highlight; blending the panel toward the theme's text color keeps a neutral band that is ~1.2x in both modes and works for generated/system themes too. | Keep the `highlight` memo and its four/two call sites; take upstream's surrounding changes. If upstream adds new `backgroundElement` highlights in this panel, point them at `highlight()` too. |
| `packages/tui/src/app.tsx` | Mounted `<EditorLabelProvider>` (fork-only `./context/editor-label`) immediately inside `<EditorContextProvider>` | The effective-editor-selection state is shared by the prompt and the sidebar footer, so it has to be provided above both. | Keep the import and the wrapper; take upstream's surrounding provider changes. If upstream moves `EditorContextProvider`, keep ours directly inside it. |
| `packages/app/index.html` | `<title>` → "CoDev Code" | Web UI tab title. | Keep our title. |
| `packages/app/src/pages/layout.tsx`, `packages/app/src/pages/layout-new.tsx` | Dropped the `<TabsInfoPopup />` mount and its import from both layouts (added upstream in v1.17.18; since v1.18.3 upstream itself removed the sibling `HelpButton`, so nothing is imported from `help-button` anymore) | `TabsInfoPopup` is a dev-channel-only "Introducing Tabs" promo whose `muted autoplay loop` `<video>` mounts on every layout render. The fork's Windows e2e runs on GPU-less GitHub-hosted runners (software GPU — see the runner-swap row), where continuous video decode wedges the GPU command buffer (`kTransientFailure`), making the whole app-e2e suite flaky and ~3–5× slower. It never ships (release builds use a non-`dev` `CODEV_CHANNEL`), so unmounting it costs users nothing. | Keep ours: don't re-add the `<TabsInfoPopup />` mount or restore it to the import. |
Expand Down
19 changes: 9 additions & 10 deletions packages/tui/src/routes/session/question.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export function QuestionPrompt(props: { request: QuestionRequest; directory?: st
const modeStack = useOpencodeModeStack()

const questions = createMemo(() => props.request.questions)
// backgroundElement is nearly identical to backgroundPanel in light themes, so derive the
// highlight from the panel and the text color instead to keep it visible in both modes
const highlight = createMemo(() => tint(theme.backgroundPanel, theme.text, 0.1))
const single = createMemo(() => questions().length === 1 && questions()[0]?.multiple !== true)
const tabs = createMemo(() => (single() ? 1 : questions().length + 1)) // questions + confirm tab (no confirm for single select)
const [tabHover, setTabHover] = createSignal<number | "confirm" | null>(null)
Expand Down Expand Up @@ -316,11 +319,7 @@ export function QuestionPrompt(props: { request: QuestionRequest; directory?: st
paddingLeft={1}
paddingRight={1}
backgroundColor={
isActive()
? theme.accent
: tabHover() === index()
? theme.backgroundElement
: theme.backgroundPanel
isActive() ? theme.accent : tabHover() === index() ? highlight() : theme.backgroundPanel
}
onMouseOver={() => setTabHover(index())}
onMouseOut={() => setTabHover(null)}
Expand Down Expand Up @@ -348,7 +347,7 @@ export function QuestionPrompt(props: { request: QuestionRequest; directory?: st
paddingLeft={1}
paddingRight={1}
backgroundColor={
confirm() ? theme.accent : tabHover() === "confirm" ? theme.backgroundElement : theme.backgroundPanel
confirm() ? theme.accent : tabHover() === "confirm" ? highlight() : theme.backgroundPanel
}
onMouseOver={() => setTabHover("confirm")}
onMouseOut={() => setTabHover(null)}
Expand Down Expand Up @@ -385,12 +384,12 @@ export function QuestionPrompt(props: { request: QuestionRequest; directory?: st
}}
>
<box flexDirection="row">
<box backgroundColor={active() ? theme.backgroundElement : undefined} paddingRight={1}>
<box backgroundColor={active() ? highlight() : undefined} paddingRight={1}>
<text fg={active() ? tint(theme.textMuted, theme.secondary, 0.6) : theme.textMuted}>
{`${i() + 1}.`}
</text>
</box>
<box backgroundColor={active() ? theme.backgroundElement : undefined}>
<box backgroundColor={active() ? highlight() : undefined}>
<text fg={active() ? theme.secondary : picked() ? theme.success : theme.text}>
{multi() ? `[${picked() ? "✓" : " "}] ${opt.label}` : opt.label}
</text>
Expand All @@ -417,12 +416,12 @@ export function QuestionPrompt(props: { request: QuestionRequest; directory?: st
}}
>
<box flexDirection="row">
<box backgroundColor={other() ? theme.backgroundElement : undefined} paddingRight={1}>
<box backgroundColor={other() ? highlight() : undefined} paddingRight={1}>
<text fg={other() ? tint(theme.textMuted, theme.secondary, 0.6) : theme.textMuted}>
{`${options().length + 1}.`}
</text>
</box>
<box backgroundColor={other() ? theme.backgroundElement : undefined}>
<box backgroundColor={other() ? highlight() : undefined}>
<text fg={other() ? theme.secondary : customPicked() ? theme.success : theme.text}>
{multi() ? `[${customPicked() ? "✓" : " "}] Type your own answer` : "Type your own answer"}
</text>
Expand Down
Loading