diff --git a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx index 91a3c8146..7ba47f8f1 100644 --- a/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx +++ b/src/web-ui/src/app/components/NavPanel/sections/workspaces/WorkspaceItem.tsx @@ -36,58 +36,7 @@ import { import { SSHContext } from '@/features/ssh-remote/SSHRemoteContext'; import { useWorkspaceSearchIndex } from '@/tools/file-explorer'; -function useStickyObserver(ref: React.RefObject) { - const [isStuck, setIsStuck] = useState(false); - useEffect(() => { - const el = ref.current; - if (!el) return; - - // Find the nearest scrollable ancestor to use as the observer root. - // The sticky element is pinned relative to this scroll container. - let scrollContainer: Element | null = el.parentElement; - while (scrollContainer) { - const style = window.getComputedStyle(scrollContainer); - const isScrollable = - (style.overflowY === 'auto' || style.overflowY === 'scroll') && - scrollContainer.scrollHeight > scrollContainer.clientHeight; - if (isScrollable) break; - scrollContainer = scrollContainer.parentElement; - } - - // Place a sentinel element as a sibling right before the sticky element. - // When the sentinel scrolls out of the top of the container, - // the sticky element is considered "stuck". - const sentinel = document.createElement('div'); - sentinel.style.position = 'static'; - sentinel.style.height = '1px'; - sentinel.style.width = '1px'; - sentinel.style.pointerEvents = 'none'; - sentinel.style.visibility = 'hidden'; - el.parentElement?.insertBefore(sentinel, el); - - const observer = new IntersectionObserver( - ([entry]) => { - // Sentinel is not intersecting → sticky element has been pushed to the top - setIsStuck(!entry.isIntersecting); - }, - { - root: scrollContainer, - threshold: 0, - rootMargin: '-1px 0px 0px 0px', - } - ); - - observer.observe(sentinel); - - return () => { - observer.disconnect(); - sentinel.remove(); - }; - }, [ref]); - - return isStuck; -} interface WorkspaceItemProps { workspace: WorkspaceInfo; isActive: boolean; @@ -144,7 +93,6 @@ const WorkspaceItem: React.FC = ({ const menuAnchorRef = useRef(null); const menuPopoverRef = useRef(null); const cardRef = useRef(null); - const isCardStuck = useStickyObserver(cardRef); const [menuPosition, setMenuPosition] = useState<{ top: number; left: number } | null>(null); const isNamedAssistantWorkspace = workspace.workspaceKind === WorkspaceKind.Assistant && @@ -399,6 +347,7 @@ const WorkspaceItem: React.FC = ({ const handleCardNameClick = useCallback(async () => { if (!isActive) { await setActiveWorkspace(workspace.id); + setSessionsCollapsed(false); } else { setSessionsCollapsed(prev => !prev); } @@ -692,18 +641,17 @@ const WorkspaceItem: React.FC = ({ aria-grabbed={draggable ? isDragging : undefined}>
{ void handleCardNameClick(); }} + style={{ cursor: 'pointer' }} > - + + + -
+
e.stopPropagation()}> + + + {searchIndexIndicator && ( <> = ({
-
+
e.stopPropagation()}>