Compare commits

...

1 Commits

Author SHA1 Message Date
Shoubhit Dash
ba4cc8119e fix(session): disable todo dock auto-scroll 2026-04-03 14:09:31 +05:30

View File

@@ -7,7 +7,7 @@ import { useSpring } from "@opencode-ai/ui/motion-spring"
import { TextReveal } from "@opencode-ai/ui/text-reveal"
import { TextStrikethrough } from "@opencode-ai/ui/text-strikethrough"
import { createResizeObserver } from "@solid-primitives/resize-observer"
import { Index, createEffect, createMemo, on, onCleanup } from "solid-js"
import { Index, createEffect, createMemo, onCleanup } from "solid-js"
import { createStore } from "solid-js/store"
import { composerEnabled, composerProbe } from "@/testing/session-composer"
import { useLanguage } from "@/context/language"
@@ -210,76 +210,25 @@ export function SessionTodoDock(props: {
opacity: `${Math.max(0, Math.min(1, 1 - hide()))}`,
}}
>
<TodoList todos={props.todos} open={!store.collapsed} />
<TodoList todos={props.todos} />
</div>
</div>
</DockTray>
)
}
function TodoList(props: { todos: Todo[]; open: boolean }) {
function TodoList(props: { todos: Todo[] }) {
const [store, setStore] = createStore({
stuck: false,
scrolling: false,
})
let scrollRef!: HTMLDivElement
let timer: number | undefined
const inProgress = createMemo(() => props.todos.findIndex((todo) => todo.status === "in_progress"))
const ensure = () => {
if (!props.open) return
if (store.scrolling) return
if (!scrollRef || scrollRef.offsetParent === null) return
const el = scrollRef.querySelector("[data-in-progress]")
if (!(el instanceof HTMLElement)) return
const topFade = 16
const bottomFade = 44
const container = scrollRef.getBoundingClientRect()
const rect = el.getBoundingClientRect()
const top = rect.top - container.top + scrollRef.scrollTop
const bottom = rect.bottom - container.top + scrollRef.scrollTop
const viewTop = scrollRef.scrollTop + topFade
const viewBottom = scrollRef.scrollTop + scrollRef.clientHeight - bottomFade
if (top < viewTop) {
scrollRef.scrollTop = Math.max(0, top - topFade)
} else if (bottom > viewBottom) {
scrollRef.scrollTop = bottom - (scrollRef.clientHeight - bottomFade)
}
setStore("stuck", scrollRef.scrollTop > 0)
}
createEffect(
on([() => props.open, inProgress], () => {
if (!props.open || inProgress() < 0) return
requestAnimationFrame(ensure)
}),
)
onCleanup(() => {
if (!timer) return
window.clearTimeout(timer)
})
return (
<div class="relative">
<div
class="px-3 pb-11 flex flex-col gap-1.5 max-h-42 overflow-y-auto no-scrollbar"
ref={scrollRef}
style={{ "overflow-anchor": "none" }}
onScroll={(e) => {
setStore("stuck", e.currentTarget.scrollTop > 0)
setStore("scrolling", true)
if (timer) window.clearTimeout(timer)
timer = window.setTimeout(() => {
setStore("scrolling", false)
if (inProgress() < 0) return
requestAnimationFrame(ensure)
}, 250)
}}
>
<Index each={props.todos}>