From cad8ea4fa7f8967c36de52218fc2e44fe7b7b262 Mon Sep 17 00:00:00 2001
From: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Date: Tue, 6 Oct 2026 10:03:04 -0700
Subject: [PATCH] fix(tabs): stop tab and close tooltips firing while grazing
the strip (#25808)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix(tabs): delay tab and close tooltips past grazing
Tab title and close-icon tooltips fired near-instantly while dragging
across the strip: Radix's provider-wide skipDelayDuration reopens the
next tooltip with no delay for 300ms after any tooltip closes.
Scope a nested TooltipProvider to the tab strip with a 700ms delay and
skipDelayDuration=0, so each tab tooltip waits the full delay.
* fix(tabs): drop close-button tooltip and lengthen tab tooltip delay
Remove the hover tooltip from the tab close button entirely (aria-label
keeps the accessible name), and raise the tab-title tooltip delay from
700ms to 1500ms so grazing or scrolling the strip no longer pops a label.
Add an interaction test proving the delay is enforced and Radix's
skip-delay is disabled.
* fix(tabs): delay the agent-state glyph tooltip to match the strip
The tab's leading agent-state dot renders its own feature tooltip with a
hardcoded 200ms delay, so tabs with a live agent state (working/done/
needs-attention) popped almost instantly while plain tabs waited the full
strip delay — the 'every other tab' inconsistency. Thread an optional
delay through StateIndicatorTooltip/AgentStateDot and pass the tab-strip
1500ms from TerminalTabLeadingIcon; other surfaces keep 200ms.
* fix(tabs): remove the agent-state glyph tooltip on tabs
Hovering a tab's status glyph (spinner/check/question) popped its own
tooltip after 200ms, so tabs with a live agent state popped while plain
tabs stayed quiet. Remove that tooltip entirely via title={null}; the
glyph stays self-describing with its aria-label, and the tab title keeps
its tooltip. Reverts the now-unused delay plumbing.
* reduce the time down from 1500 ms to 500 ms
* fix(tabs): restore the close-tab shortcut hint with a slower delay
Close buttons share one TabCloseTooltip that waits 1s, longer than the 500ms tab-title tooltip. Also merges the tooltip provider tests.
---
.../tab-bar/EditorFileTabCloseButton.tsx | 66 ++++++--------
.../src/components/tab-bar/SortableTab.tsx | 75 +++++++---------
.../tab-bar/TabBar.context-menu.test.ts | 12 +--
.../TabBar.windows-shell-launch.test.ts | 4 +-
...abBar.windows-shell-remote-runtime.test.ts | 4 +-
.../TabBar.windows-shell-ssh-host.test.ts | 4 +-
.../components/tab-bar/TabCloseTooltip.tsx | 25 ++++++
.../tab-bar/TabStripTooltipProvider.test.tsx | 88 +++++++++++++++++++
.../tab-bar/TabStripTooltipProvider.tsx | 16 ++++
...minalTabLeadingIcon.state-tooltip.test.tsx | 29 ++++++
.../tab-bar/TerminalTabLeadingIcon.tsx | 3 +-
.../components/tab-bar/tab-bar-surface.tsx | 23 ++---
...b-bar-windows-shell-launch-render-stubs.ts | 15 ++++
13 files changed, 264 insertions(+), 100 deletions(-)
create mode 100644 src/renderer/src/components/tab-bar/TabCloseTooltip.tsx
create mode 100644 src/renderer/src/components/tab-bar/TabStripTooltipProvider.test.tsx
create mode 100644 src/renderer/src/components/tab-bar/TabStripTooltipProvider.tsx
create mode 100644 src/renderer/src/components/tab-bar/TerminalTabLeadingIcon.state-tooltip.test.tsx
diff --git a/src/renderer/src/components/tab-bar/EditorFileTabCloseButton.tsx b/src/renderer/src/components/tab-bar/EditorFileTabCloseButton.tsx
index 98ef2712dbf..d8fc28a881c 100644
--- a/src/renderer/src/components/tab-bar/EditorFileTabCloseButton.tsx
+++ b/src/renderer/src/components/tab-bar/EditorFileTabCloseButton.tsx
@@ -1,7 +1,6 @@
import { X } from 'lucide-react'
-import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
-import { useOptionalShortcutLabel } from '@/hooks/useShortcutLabel'
import { translate } from '@/i18n/i18n'
+import { TabCloseTooltip } from './TabCloseTooltip'
export function EditorFileTabCloseButton({
fileIsDirty,
@@ -12,43 +11,32 @@ export function EditorFileTabCloseButton({
showsSelectionChrome: boolean
onClose: () => void
}): React.JSX.Element {
- const closeShortcut = useOptionalShortcutLabel('tab.close')
- const closeLabel = translate(
- 'auto.components.tab.bar.EditorFileTabCloseButton.a768f428f1',
- 'Close tab'
- )
-
return (
-
-
-
-
-
- {closeShortcut ? `${closeLabel} (${closeShortcut})` : closeLabel}
-
-
+
+
+
)
}
diff --git a/src/renderer/src/components/tab-bar/SortableTab.tsx b/src/renderer/src/components/tab-bar/SortableTab.tsx
index 3f128f811fa..763f3b7f131 100644
--- a/src/renderer/src/components/tab-bar/SortableTab.tsx
+++ b/src/renderer/src/components/tab-bar/SortableTab.tsx
@@ -22,8 +22,8 @@ import { SortableTabContextMenu } from './SortableTabContextMenu'
import { translate } from '@/i18n/i18n'
import { TAB_LABEL_WIDTH_CLASSES } from './tab-width-rules'
import { useTabStripSlotProps } from './use-tab-strip-slot-props'
-import { useOptionalShortcutLabel } from '@/hooks/useShortcutLabel'
import { useTabStripPointerActivation } from './tab-strip-pointer-activation'
+import { TabCloseTooltip } from './TabCloseTooltip'
import { TerminalTabLeadingIcon } from './TerminalTabLeadingIcon'
import {
isTerminalTabActivityLive,
@@ -174,8 +174,6 @@ export default function SortableTab({
disabled: isEditing
})
const slotProps = useTabStripSlotProps(tab.id, isActive)
- const closeShortcut = useOptionalShortcutLabel('tab.close')
- const closeLabel = translate('auto.components.tab.bar.SortableTab.95db5f2f7d', 'Close tab')
const tabTitle = tab.customTitle ?? tab.title
const tabRoot = (