diff options
| author | David Hill <[email protected]> | 2026-01-27 02:29:56 +0000 |
|---|---|---|
| committer | David Hill <[email protected]> | 2026-01-27 14:04:10 +0000 |
| commit | 52387e7f3325ab316830c3a90751df2928151c6f (patch) | |
| tree | 5200f0de4596b5a555ba9734cf7c3e7bb8671938 | |
| parent | ebfa2b57da606350afc0693c3d08b15eeaedd877 (diff) | |
| download | opencode-52387e7f3325ab316830c3a90751df2928151c6f.tar.gz opencode-52387e7f3325ab316830c3a90751df2928151c6f.zip | |
fix(app): only show left border on plus button when sticky
| -rw-r--r-- | packages/app/src/pages/session.tsx | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index d695f0ba2..91f481fdf 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1,4 +1,16 @@ -import { For, onCleanup, onMount, Show, Match, Switch, createMemo, createEffect, on } from "solid-js" +import { + For, + onCleanup, + onMount, + Show, + Match, + Switch, + createMemo, + createEffect, + createSignal, + on, + type JSX, +} from "solid-js" import { createMediaQuery } from "@solid-primitives/media" import { createResizeObserver } from "@solid-primitives/resize-observer" import { Dynamic } from "solid-js/web" @@ -86,6 +98,44 @@ interface SessionReviewTabProps { } } +function StickyAddButton(props: { children: JSX.Element }) { + const [stuck, setStuck] = createSignal(false) + let button: HTMLDivElement | undefined + + createEffect(() => { + const node = button + if (!node) return + + const scroll = node.parentElement + if (!scroll) return + + const handler = () => { + const rect = node.getBoundingClientRect() + const scrollRect = scroll.getBoundingClientRect() + setStuck(rect.right >= scrollRect.right && scroll.scrollWidth > scroll.clientWidth) + } + + scroll.addEventListener("scroll", handler, { passive: true }) + const observer = new ResizeObserver(handler) + observer.observe(scroll) + handler() + onCleanup(() => { + scroll.removeEventListener("scroll", handler) + observer.disconnect() + }) + }) + + return ( + <div + ref={button} + class="bg-background-base h-full shrink-0 sticky right-0 z-10 flex items-center justify-center border-b border-border-weak-base px-3" + classList={{ "border-l": stuck() }} + > + {props.children} + </div> + ) +} + function SessionReviewTab(props: SessionReviewTabProps) { let scroll: HTMLDivElement | undefined let frame: number | undefined @@ -2007,7 +2057,7 @@ export default function Page() { {(tab) => <SortableTab tab={tab} onTabClose={tabs().close} />} </For> </SortableProvider> - <div class="bg-background-base h-full shrink-0 sticky right-0 z-10 flex items-center justify-center border-b border-l border-border-weak-base px-3"> + <StickyAddButton> <TooltipKeybind title={language.t("command.file.open")} keybind={command.keybind("file.open")} @@ -2021,7 +2071,7 @@ export default function Page() { aria-label={language.t("command.file.open")} /> </TooltipKeybind> - </div> + </StickyAddButton> </Tabs.List> </div> <Show when={!layout.fileTree.opened()}> |
