From f9ef27842a50cb524e9218fd24a6a88b5d5aaabb Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Mon, 23 Feb 2026 10:42:06 +1000 Subject: [PATCH 1/3] fix(tui): align sidebar and global scroll physics with config --- packages/opencode/src/cli/cmd/tui/app.tsx | 3 ++- .../cmd/tui/component/prompt/autocomplete.tsx | 3 +++ .../src/cli/cmd/tui/routes/session/index.tsx | 23 ++----------------- .../cli/cmd/tui/routes/session/permission.tsx | 3 +++ .../cli/cmd/tui/routes/session/sidebar.tsx | 4 ++++ .../src/cli/cmd/tui/ui/dialog-select.tsx | 6 +++++ .../opencode/src/cli/cmd/tui/util/scroll.ts | 23 +++++++++++++++++++ 7 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 packages/opencode/src/cli/cmd/tui/util/scroll.ts diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index ab3d09689252..b38ad60d0819 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -38,6 +38,7 @@ import { ArgsProvider, useArgs, type Args } from "./context/args" import open from "open" import { writeHeapSnapshot } from "v8" import { PromptRefProvider, usePromptRef } from "./context/prompt" +import { getScrollAcceleration } from "./util/scroll" async function getTerminalBackgroundColor(): Promise<"dark" | "light"> { // can't set raw mode if not a TTY @@ -831,7 +832,7 @@ function ErrorComponent(props: { Exit - + {props.error.stack} {props.error.message} 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 3240afab326a..c3eed5eac2e8 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -6,6 +6,7 @@ import { createMemo, createResource, createEffect, onMount, onCleanup, Index, Sh import { createStore } from "solid-js/store" import { useSDK } from "@tui/context/sdk" import { useSync } from "@tui/context/sync" +import { getScrollAcceleration } from "../../util/scroll" import { useTheme, selectedForeground } from "@tui/context/theme" import { SplitBorder } from "@tui/component/border" import { useCommandDialog } from "@tui/component/dialog-command" @@ -605,6 +606,7 @@ export function Autocomplete(props: { }) let scroll: ScrollBoxRenderable + const scrollAcceleration = createMemo(() => getScrollAcceleration(sync.data.config.tui)) return ( timestamps() === "show") const contentWidth = createMemo(() => dimensions().width - (sidebarVisible() ? 42 : 0) - 4) - const scrollAcceleration = createMemo(() => { - const tui = sync.data.config.tui - if (tui?.scroll_acceleration?.enabled) { - return new MacOSScrollAccel() - } - if (tui?.scroll_speed) { - return new CustomSpeedScroll(tui.scroll_speed) - } - - return new CustomSpeedScroll(3) - }) + const scrollAcceleration = createMemo(() => getScrollAcceleration(sync.data.config.tui)) createEffect(async () => { await sync.session diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx index 389fc2418cc6..7abb38239aa4 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -15,6 +15,7 @@ import { Keybind } from "@/util/keybind" import { Locale } from "@/util/locale" import { Global } from "@/global" import { useDialog } from "../../ui/dialog" +import { getScrollAcceleration } from "../../util/scroll" type PermissionStage = "permission" | "always" | "reject" @@ -61,12 +62,14 @@ function EditBody(props: { request: PermissionRequest }) { }) const ft = createMemo(() => filetype(filepath())) + const scrollAcceleration = createMemo(() => getScrollAcceleration(sync.data.config.tui)) return ( sync.data.session_diff[props.sessionID] ?? []) const todo = createMemo(() => sync.data.todo[props.sessionID] ?? []) const messages = createMemo(() => sync.data.message[props.sessionID] ?? []) + const scrollAcceleration = createMemo(() => getScrollAcceleration(sync.data.config.tui)) const [expanded, setExpanded] = createStore({ mcp: true, @@ -82,6 +85,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { > { title: string @@ -50,6 +52,9 @@ export type DialogSelectRef = { export function DialogSelect(props: DialogSelectProps) { const dialog = useDialog() const { theme } = useTheme() + const sync = useSync() + const scrollAcceleration = createMemo(() => getScrollAcceleration(sync.data.config.tui)) + const [store, setStore] = createStore({ selected: 0, filter: "", @@ -275,6 +280,7 @@ export function DialogSelect(props: DialogSelectProps) { paddingLeft={1} paddingRight={1} scrollbarOptions={{ visible: false }} + scrollAcceleration={scrollAcceleration()} ref={(r: ScrollBoxRenderable) => (scroll = r)} maxHeight={height()} > diff --git a/packages/opencode/src/cli/cmd/tui/util/scroll.ts b/packages/opencode/src/cli/cmd/tui/util/scroll.ts new file mode 100644 index 000000000000..d34f0d48a09a --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/util/scroll.ts @@ -0,0 +1,23 @@ +import { MacOSScrollAccel, type ScrollAcceleration } from "@opentui/core" +import type { Config } from "@opencode-ai/sdk/v2" + +export class CustomSpeedScroll implements ScrollAcceleration { + constructor(private speed: number) {} + + tick(_now?: number): number { + return this.speed + } + + reset(): void {} +} + +export function getScrollAcceleration(tuiConfig?: Config["tui"]): ScrollAcceleration { + if (tuiConfig?.scroll_acceleration?.enabled) { + return new MacOSScrollAccel() + } + if (tuiConfig?.scroll_speed) { + return new CustomSpeedScroll(tuiConfig.scroll_speed) + } + + return new CustomSpeedScroll(3) +} From 7d48823ff764ce8b6bd019c95a8473e7c78d1086 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:00:35 +1000 Subject: [PATCH 2/3] remove test_resolve.ts --- packages/opencode/test_resolve.ts | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 packages/opencode/test_resolve.ts diff --git a/packages/opencode/test_resolve.ts b/packages/opencode/test_resolve.ts deleted file mode 100644 index f4aaf8f2ac58..000000000000 --- a/packages/opencode/test_resolve.ts +++ /dev/null @@ -1,2 +0,0 @@ -import core from "@opentui/core" -console.log(require.resolve("@opentui/core")) From c4d2178b33fb758d9ce893373d205cdba911807d Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:04:58 +1000 Subject: [PATCH 3/3] chore: remove temporary test files --- packages/opencode/test_renderable.ts | 2 -- temp.ts | 1 - 2 files changed, 3 deletions(-) delete mode 100644 packages/opencode/test_renderable.ts delete mode 100644 temp.ts diff --git a/packages/opencode/test_renderable.ts b/packages/opencode/test_renderable.ts deleted file mode 100644 index bb411ce43f25..000000000000 --- a/packages/opencode/test_renderable.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { Renderable } from "@opentui/core" -console.log(typeof ({} as Renderable).hasSelection) diff --git a/temp.ts b/temp.ts deleted file mode 100644 index 3b8dd03d21d5..000000000000 --- a/temp.ts +++ /dev/null @@ -1 +0,0 @@ -import { Renderable } from "@opentui/core"; type T = Renderable["hasSelection"];