diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index 5cc421db3542..9d057a3d2980 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -10,7 +10,6 @@ import { TerminalSquare, Volume2, VolumeOff, - X, } from "lucide-react"; import { type KeyboardEvent as ReactKeyboardEvent, @@ -33,6 +32,7 @@ import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; import { Kbd } from "~/components/ui/kbd"; import { Menu, MenuItem, MenuPopup, MenuShortcut, MenuTrigger } from "~/components/ui/menu"; import { ScrollArea } from "~/components/ui/scroll-area"; +import { PanelTabCloseButton } from "~/components/ui/panel-tab-close-button"; import { faviconUrlForOrigin } from "~/lib/favicon"; import { useTheme } from "~/hooks/useTheme"; import { COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS } from "~/workspaceTitlebar"; @@ -823,29 +823,24 @@ export function RightPanelTabs(props: RightPanelTabsProps) { : "text-muted-foreground hover:bg-accent/60 hover:text-foreground", )} > - + ) : null} + {audio === "none" || !audioRuntimeTabId ? null : (
- {resolvedTerminalGroups.map((terminalGroup, groupIndex) => { + {resolvedTerminalGroups.map((terminalGroup) => { const isGroupActive = terminalGroup.terminalIds.includes(resolvedActiveTerminalId); const groupActiveTerminalId = isGroupActive ? resolvedActiveTerminalId : (terminalGroup.terminalIds[0] ?? resolvedActiveTerminalId); + const terminalCount = terminalGroup.terminalIds.length; + const isSplitGroup = terminalCount > 1; + const groupLabel = !isSplitGroup + ? "Single" + : terminalGroup.splitDirection === "vertical" + ? "Stacked" + : "Side by side"; + const GroupIcon = !isSplitGroup + ? Square + : terminalGroup.splitDirection === "vertical" + ? SquareSplitVertical + : SquareSplitHorizontal; return (
{showGroupHeaders && ( )} -
+
{terminalGroup.terminalIds.map((terminalId) => { const isActive = terminalId === resolvedActiveTerminalId; - const closeTerminalLabel = `Close ${ - terminalLabelById.get(terminalId) ?? "terminal" - }${isActive && closeShortcutLabel ? ` (${closeShortcutLabel})` : ""}`; + const terminalLabel = terminalLabelById.get(terminalId) ?? "Terminal"; + const closeTerminalLabel = `Close ${terminalLabel}${ + isActive && closeShortcutLabel ? ` (${closeShortcutLabel})` : "" + }`; return (
- {showGroupHeaders && ( - + : "text-muted-foreground hover:bg-accent/60 hover:text-foreground", )} + > + confirmCloseTerminal(terminalId)} + tooltip={closeTerminalLabel} + > + + - {normalizedTerminalIds.length > 1 && ( - - confirmCloseTerminal(terminalId)} - aria-label={closeTerminalLabel} - /> - } - > - - - - {closeTerminalLabel} - - - )}
); })} diff --git a/apps/web/src/components/ui/panel-tab-close-button.tsx b/apps/web/src/components/ui/panel-tab-close-button.tsx new file mode 100644 index 000000000000..0e17a8f23a38 --- /dev/null +++ b/apps/web/src/components/ui/panel-tab-close-button.tsx @@ -0,0 +1,41 @@ +import { X } from "lucide-react"; +import type { ReactNode } from "react"; +import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; + +interface PanelTabCloseButtonProps { + children: ReactNode; + label: string; + onClick: () => void; + tooltip?: string; +} + +/** Inside a `group/tab` row, swaps the tab identity for its close action on hover or focus. */ +export function PanelTabCloseButton({ + children, + label, + onClick, + tooltip, +}: PanelTabCloseButtonProps) { + const button = ( + + ); + + if (!tooltip) return button; + + return ( + + + {tooltip} + + ); +}