|
|
@@ -1,6 +1,5 @@
|
|
|
import { HoverCard as Kobalte } from "@kobalte/core/hover-card"
|
|
|
-import { Show, type JSXElement } from "solid-js"
|
|
|
-import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
|
|
|
+import { createSignal, Show, type JSXElement } from "solid-js"
|
|
|
import "./titlebar-tab-popover.css"
|
|
|
|
|
|
// Initial hover delay before the preview appears, per design.
|
|
|
@@ -10,14 +9,13 @@ const CLOSE_DELAY = 0
|
|
|
// After a preview closes, hovering a neighbouring tab within this window skips
|
|
|
// the open delay — mirrors the tooltip's skipDelayDuration so moving across
|
|
|
// tabs doesn't re-wait the full delay each time.
|
|
|
-const SKIP_WINDOW = 300
|
|
|
+const SKIP_WINDOW = 500
|
|
|
let lastClosedAt = 0
|
|
|
|
|
|
export interface TabPreviewData {
|
|
|
projectName?: string
|
|
|
title?: string
|
|
|
path?: string
|
|
|
- branch?: string
|
|
|
serverName?: string
|
|
|
}
|
|
|
|
|
|
@@ -28,12 +26,18 @@ export function TabPreviewPopover(props: {
|
|
|
data: TabPreviewData
|
|
|
}) {
|
|
|
let triggerEl: HTMLDivElement | undefined
|
|
|
+ // When opened during a rapid tab-hopping streak, this preview appears and
|
|
|
+ // disappears instantly (no repeated enter/exit animation) — only the first,
|
|
|
+ // "cold" preview animates. Mirrors how browsers reuse one tab tooltip.
|
|
|
+ const [instant, setInstant] = createSignal(false)
|
|
|
|
|
|
+ const warm = () => Date.now() - lastClosedAt < SKIP_WINDOW
|
|
|
// Kobalte reads openDelay lazily when the pointer enters the trigger, so this
|
|
|
// resolves the skip window per-hover.
|
|
|
- const resolveOpenDelay = () => (Date.now() - lastClosedAt < SKIP_WINDOW ? 0 : OPEN_DELAY)
|
|
|
+ const resolveOpenDelay = () => (warm() ? 0 : OPEN_DELAY)
|
|
|
const handleOpenChange = (open: boolean) => {
|
|
|
- if (!open) lastClosedAt = Date.now()
|
|
|
+ if (open) setInstant(warm())
|
|
|
+ else lastClosedAt = Date.now()
|
|
|
props.onOpenChange(open)
|
|
|
}
|
|
|
|
|
|
@@ -61,6 +65,7 @@ export function TabPreviewPopover(props: {
|
|
|
if (theme) el.setAttribute("data-theme", theme)
|
|
|
}}
|
|
|
data-component="session-tab-popover"
|
|
|
+ data-instant={instant() || undefined}
|
|
|
>
|
|
|
<div data-slot="header">
|
|
|
<Show when={props.data.projectName}>
|
|
|
@@ -73,22 +78,10 @@ export function TabPreviewPopover(props: {
|
|
|
|
|
|
<Show when={props.data.path}>
|
|
|
<div data-slot="row">
|
|
|
- <span data-slot="icon">
|
|
|
- <IconV2 name="folder" />
|
|
|
- </span>
|
|
|
<span data-slot="detail">{props.data.path}</span>
|
|
|
</div>
|
|
|
</Show>
|
|
|
|
|
|
- <Show when={props.data.branch}>
|
|
|
- <div data-slot="row">
|
|
|
- <span data-slot="icon">
|
|
|
- <IconV2 name="branch" />
|
|
|
- </span>
|
|
|
- <span data-slot="detail">{props.data.branch}</span>
|
|
|
- </div>
|
|
|
- </Show>
|
|
|
-
|
|
|
<Show when={props.data.serverName}>
|
|
|
<div data-slot="server">{props.data.serverName}</div>
|
|
|
</Show>
|