summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorShoubhit Dash <[email protected]>2026-03-23 12:55:30 +0530
committerGitHub <[email protected]>2026-03-23 07:25:30 +0000
commit5ea95451dd485b15696877a9dd82c30a532b68e0 (patch)
tree3adca097c59f528e3640e30eeabdd7ff4a686011
parent9239d877b9602a5a80e9e69e744abfe011f5f991 (diff)
downloadopencode-5ea95451dd485b15696877a9dd82c30a532b68e0.tar.gz
opencode-5ea95451dd485b15696877a9dd82c30a532b68e0.zip
fix(app): prevent stale session hover preview on refocus (#18727)
-rw-r--r--packages/app/src/pages/layout.tsx18
-rw-r--r--packages/app/src/pages/layout/sidebar-items.tsx65
2 files changed, 54 insertions, 29 deletions
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 0c10cc89b..88572503f 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -211,13 +211,22 @@ export default function Layout(props: ParentProps) {
onMount(() => {
const stop = () => setState("sizing", false)
+ const blur = () => reset()
+ const hide = () => {
+ if (document.visibilityState !== "hidden") return
+ reset()
+ }
window.addEventListener("pointerup", stop)
window.addEventListener("pointercancel", stop)
window.addEventListener("blur", stop)
+ window.addEventListener("blur", blur)
+ document.addEventListener("visibilitychange", hide)
onCleanup(() => {
window.removeEventListener("pointerup", stop)
window.removeEventListener("pointercancel", stop)
window.removeEventListener("blur", stop)
+ window.removeEventListener("blur", blur)
+ document.removeEventListener("visibilitychange", hide)
})
})
@@ -237,6 +246,12 @@ export default function Layout(props: ParentProps) {
navLeave.current = undefined
}
+ const reset = () => {
+ disarm()
+ setState("hoverSession", undefined)
+ setHoverProject(undefined)
+ }
+
const arm = () => {
if (layout.sidebar.opened()) return
if (state.hoverProject === undefined) return
@@ -305,8 +320,7 @@ export default function Layout(props: ParentProps) {
const clearSidebarHoverState = () => {
if (layout.sidebar.opened()) return
- setState("hoverSession", undefined)
- setHoverProject(undefined)
+ reset()
}
const navigateWithSidebarReset = (href: string) => {
diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx
index f8e16f3e1..a9627c5db 100644
--- a/packages/app/src/pages/layout/sidebar-items.tsx
+++ b/packages/app/src/pages/layout/sidebar-items.tsx
@@ -157,34 +157,45 @@ const SessionHoverPreview = (props: {
messageLabel: (message: Message) => string | undefined
onMessageSelect: (message: Message) => void
trigger: JSX.Element
-}): JSX.Element => (
- <HoverCard
- openDelay={1000}
- closeDelay={props.sidebarHovering() ? 600 : 0}
- placement="right-start"
- gutter={16}
- shift={-2}
- trigger={props.trigger}
- open={props.hoverSession() === props.session.id}
- onOpenChange={(open) => props.setHoverSession(open ? props.session.id : undefined)}
- >
- <Show
- when={props.hoverReady()}
- fallback={<div class="text-12-regular text-text-weak">{props.language.t("session.messages.loading")}</div>}
+}): JSX.Element => {
+ let ref: HTMLDivElement | undefined
+
+ return (
+ <HoverCard
+ openDelay={1000}
+ closeDelay={props.sidebarHovering() ? 600 : 0}
+ placement="right-start"
+ gutter={16}
+ shift={-2}
+ trigger={<div ref={ref}>{props.trigger}</div>}
+ open={props.hoverSession() === props.session.id}
+ onOpenChange={(open) => {
+ if (!open) {
+ props.setHoverSession(undefined)
+ return
+ }
+ if (!ref?.matches(":hover")) return
+ props.setHoverSession(props.session.id)
+ }}
>
- <div class="overflow-y-auto overflow-x-hidden max-h-72 h-full">
- <MessageNav
- messages={props.hoverMessages() ?? []}
- current={undefined}
- getLabel={props.messageLabel}
- onMessageSelect={props.onMessageSelect}
- size="normal"
- class="w-60"
- />
- </div>
- </Show>
- </HoverCard>
-)
+ <Show
+ when={props.hoverReady()}
+ fallback={<div class="text-12-regular text-text-weak">{props.language.t("session.messages.loading")}</div>}
+ >
+ <div class="overflow-y-auto overflow-x-hidden max-h-72 h-full">
+ <MessageNav
+ messages={props.hoverMessages() ?? []}
+ current={undefined}
+ getLabel={props.messageLabel}
+ onMessageSelect={props.onMessageSelect}
+ size="normal"
+ class="w-60"
+ />
+ </div>
+ </Show>
+ </HoverCard>
+ )
+}
export const SessionItem = (props: SessionItemProps): JSX.Element => {
const params = useParams()