summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Hill <[email protected]>2026-01-27 02:29:56 +0000
committerDavid Hill <[email protected]>2026-01-27 14:04:10 +0000
commit52387e7f3325ab316830c3a90751df2928151c6f (patch)
tree5200f0de4596b5a555ba9734cf7c3e7bb8671938
parentebfa2b57da606350afc0693c3d08b15eeaedd877 (diff)
downloadopencode-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.tsx56
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()}>