diff --git a/src/renderer/components/TabBar.tsx b/src/renderer/components/TabBar.tsx index 547120b262..c37fbcb80e 100644 --- a/src/renderer/components/TabBar.tsx +++ b/src/renderer/components/TabBar.tsx @@ -8,7 +8,7 @@ import { Text, } from "@radix-ui/themes"; import type React from "react"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { useTabStore } from "../stores/tabStore"; @@ -27,6 +27,8 @@ export function TabBar() { const [dropPosition, setDropPosition] = useState<"left" | "right" | null>( null, ); + const [showScrollGradient, setShowScrollGradient] = useState(false); + const scrollContainerRef = useRef(null); // Keyboard navigation handlers const handlePrevTab = useCallback(() => { @@ -166,101 +168,175 @@ export function TabBar() { setDropPosition(null); }, []); + const checkScrollGradient = useCallback(() => { + const container = scrollContainerRef.current; + if (!container) return; + + const canScrollRight = + container.scrollWidth > container.clientWidth && + container.scrollLeft + container.clientWidth < container.scrollWidth - 1; + + setShowScrollGradient(canScrollRight); + }, []); + + useEffect(() => { + checkScrollGradient(); + + const container = scrollContainerRef.current; + if (!container) return; + + container.addEventListener("scroll", checkScrollGradient); + window.addEventListener("resize", checkScrollGradient); + + return () => { + container.removeEventListener("scroll", checkScrollGradient); + window.removeEventListener("resize", checkScrollGradient); + }; + }, [checkScrollGradient]); + + useEffect(() => { + checkScrollGradient(); + }, [checkScrollGradient]); + + useEffect(() => { + const container = scrollContainerRef.current; + if (!container) return; + + const activeTabElement = container.querySelector( + `[data-tab-id="${activeTabId}"]`, + ); + if (activeTabElement) { + activeTabElement.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "nearest", + }); + } + }, [activeTabId]); + return ( {/* Spacer for macOS window controls */} - {tabs.map((tab, index) => { - const isDragging = draggedTab === tab.id; - const isDragOver = dragOverTab === tab.id; - const showLeftIndicator = isDragOver && dropPosition === "left"; - const showRightIndicator = isDragOver && dropPosition === "right"; - - return ( - - - setActiveTab(tab.id)} - onDragStart={(e) => handleDragStart(e, tab.id)} - onDragOver={(e) => handleDragOver(e, tab.id)} - onDragLeave={handleDragLeave} - onDrop={(e) => handleDrop(e, tab.id)} - onDragEnd={handleDragEnd} - > - {showLeftIndicator && ( - - )} - - {showRightIndicator && ( - - )} - {index < 9 && ( - - {navigator.platform.includes("Mac") ? "⌘" : "Ctrl+"} - {index + 1} - - )} - - + {tabs.map((tab, index) => { + const isDragging = draggedTab === tab.id; + const isDragOver = dragOverTab === tab.id; + const showLeftIndicator = isDragOver && dropPosition === "left"; + const showRightIndicator = isDragOver && dropPosition === "right"; + + return ( + + + setActiveTab(tab.id)} + onDragStart={(e) => handleDragStart(e, tab.id)} + onDragOver={(e) => handleDragOver(e, tab.id)} + onDragLeave={handleDragLeave} + onDrop={(e) => handleDrop(e, tab.id)} + onDragEnd={handleDragEnd} > - {tab.title} - - - {tabs.length > 1 && ( - { - e.stopPropagation(); - closeTab(tab.id); - }} + {showLeftIndicator && ( + + )} + + {showRightIndicator && ( + + )} + {index < 9 && ( + + {navigator.platform.includes("Mac") ? "⌘" : "Ctrl+"} + {index + 1} + + )} + + - - - )} - - - - closeOtherTabs(tab.id)} - > - Close other tabs - - closeTabsToRight(tab.id)} - > - Close tabs to the right - - - - ); - })} + {tab.title} + + + {tabs.length > 1 && ( + { + e.stopPropagation(); + closeTab(tab.id); + }} + > + + + )} + + + + closeOtherTabs(tab.id)} + > + Close other tabs + + closeTabsToRight(tab.id)} + > + Close tabs to the right + + + + ); + })} + + + {showScrollGradient && ( + + )} ); } diff --git a/src/renderer/styles/globals.css b/src/renderer/styles/globals.css index 3eb21a6a99..d47d813652 100644 --- a/src/renderer/styles/globals.css +++ b/src/renderer/styles/globals.css @@ -36,6 +36,10 @@ body { -webkit-app-region: no-drag; } +.scrollbar-hide::-webkit-scrollbar { + display: none; +} + /* File mention list styles */ .file-mention-item { padding: var(--space-2);