diff options
| author | Adam <[email protected]> | 2025-12-29 09:47:53 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-29 09:47:57 -0600 |
| commit | 831e9bce51c035ec22ce9562bf0257d6b59b2fe4 (patch) | |
| tree | b6e86b44cbc980d737a63cb571cb61a9003d237b /packages/ui/src/components/list.tsx | |
| parent | 5de73abd820d9425e82f85f95f50568332ca7cdc (diff) | |
| download | opencode-831e9bce51c035ec22ce9562bf0257d6b59b2fe4.tar.gz opencode-831e9bce51c035ec22ce9562bf0257d6b59b2fe4.zip | |
fix(desktop): jankiness
Diffstat (limited to 'packages/ui/src/components/list.tsx')
| -rw-r--r-- | packages/ui/src/components/list.tsx | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index 808c9b032..a549c19e9 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -1,5 +1,5 @@ import { type FilteredListProps, useFilteredList } from "@opencode-ai/ui/hooks" -import { createEffect, createSignal, For, type JSX, on, Show } from "solid-js" +import { createEffect, createSignal, For, onCleanup, type JSX, on, Show } from "solid-js" import { createStore } from "solid-js/store" import { Icon, type IconProps } from "./icon" import { IconButton } from "./icon-button" @@ -116,6 +116,33 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void }) setScrollRef, }) + function GroupHeader(props: { category: string }): JSX.Element { + const [stuck, setStuck] = createSignal(false) + const [header, setHeader] = createSignal<HTMLDivElement | undefined>(undefined) + + createEffect(() => { + const scroll = scrollRef() + const node = header() + if (!scroll || !node) return + + const handler = () => { + const rect = node.getBoundingClientRect() + const scrollRect = scroll.getBoundingClientRect() + setStuck(rect.top <= scrollRect.top + 1 && scroll.scrollTop > 0) + } + + scroll.addEventListener("scroll", handler, { passive: true }) + handler() + onCleanup(() => scroll.removeEventListener("scroll", handler)) + }) + + return ( + <div data-slot="list-header" data-stuck={stuck()} ref={setHeader}> + {props.category} + </div> + ) + } + return ( <div data-component="list" classList={{ [props.class ?? ""]: !!props.class }}> <Show when={!!props.search}> @@ -157,31 +184,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void }) {(group) => ( <div data-slot="list-group"> <Show when={group.category}> - {(() => { - const [stuck, setStuck] = createSignal(false) - return ( - <div - data-slot="list-header" - data-stuck={stuck()} - ref={(el) => { - createEffect(() => { - const scroll = scrollRef() - if (!scroll) return - const handler = () => { - const rect = el.getBoundingClientRect() - const scrollRect = scroll.getBoundingClientRect() - setStuck(rect.top <= scrollRect.top + 1 && scroll.scrollTop > 0) - } - scroll.addEventListener("scroll", handler, { passive: true }) - handler() - return () => scroll.removeEventListener("scroll", handler) - }) - }} - > - {group.category} - </div> - ) - })()} + <GroupHeader category={group.category} /> </Show> <div data-slot="list-items"> <For each={group.items}> |
