From 02a5484a7812b0fe9a104a19447813c4eb13f953 Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 19:49:28 -0500 Subject: [PATCH 1/6] small fixes for auto scroll on new items --- .../workspace-canvas/FolderCard.tsx | 26 +++---------------- .../workspace-canvas/WorkspaceHeader.tsx | 9 ++++++- .../workspace-canvas/WorkspaceSection.tsx | 12 +++++++-- src/hooks/ui/use-reactive-navigation.ts | 9 ++----- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/components/workspace-canvas/FolderCard.tsx b/src/components/workspace-canvas/FolderCard.tsx index dbc8f377..8ec7c852 100644 --- a/src/components/workspace-canvas/FolderCard.tsx +++ b/src/components/workspace-canvas/FolderCard.tsx @@ -85,7 +85,6 @@ function FolderCardComponent({ const [isDragHover, setIsDragHover] = useState(false); const [selectedCount, setSelectedCount] = useState(null); const [isEditingTitle, setIsEditingTitle] = useState(false); - const [shouldAutoFocus, setShouldAutoFocus] = useState(false); // Subscribe directly to this folder's selection state from the store const isSelected = useUIStore( @@ -103,19 +102,8 @@ function FolderCardComponent({ const folderColor = item.color || "#6366F1"; // Default to indigo - // Auto-focus and scroll into view for newly created folders (name is "New Folder") - useEffect(() => { - if (item.name === "New Folder") { - setShouldAutoFocus(true); - // Scroll the folder card into view - const element = document.getElementById(`item-${item.id}`); - if (element) { - setTimeout(() => { - element.scrollIntoView({ behavior: 'smooth', block: 'center' }); - }, 100); - } - } - }, [item.id, item.name]); + // Note: Auto-focus removed - user must click to edit title + // Scroll behavior is handled by useReactiveNavigation hook // Listen for drag hover events useEffect(() => { @@ -406,19 +394,13 @@ function FolderCardComponent({ subtitle="" description="" onNameChange={handleNameChange} - onNameCommit={(value) => { - handleNameCommit(value); - // Clear auto-focus after first commit - if (shouldAutoFocus) { - setShouldAutoFocus(false); - } - }} + onNameCommit={handleNameCommit} onSubtitleChange={() => { }} onTitleFocus={() => setIsEditingTitle(true)} onTitleBlur={() => setIsEditingTitle(false)} readOnly={false} noMargin={true} - autoFocus={shouldAutoFocus} + autoFocus={false} /> {/* Item count as subtext */}

diff --git a/src/components/workspace-canvas/WorkspaceHeader.tsx b/src/components/workspace-canvas/WorkspaceHeader.tsx index f2b49721..8416e4b3 100644 --- a/src/components/workspace-canvas/WorkspaceHeader.tsx +++ b/src/components/workspace-canvas/WorkspaceHeader.tsx @@ -974,7 +974,14 @@ export default function WorkspaceHeader({ } } }, - onCreateFolder: () => { if (addItem) addItem("folder"); }, + onCreateFolder: () => { + if (addItem) { + const itemId = addItem("folder"); + if (onItemCreated && itemId) { + onItemCreated([itemId]); + } + } + }, onUpload: () => { setShowUploadDialog(true); setIsNewMenuOpen(false); }, onAudio: () => { openAudioDialog(); setIsNewMenuOpen(false); }, onYouTube: () => { setShowYouTubeDialog(true); setIsNewMenuOpen(false); }, diff --git a/src/components/workspace-canvas/WorkspaceSection.tsx b/src/components/workspace-canvas/WorkspaceSection.tsx index e21ca7a0..91d9b27b 100644 --- a/src/components/workspace-canvas/WorkspaceSection.tsx +++ b/src/components/workspace-canvas/WorkspaceSection.tsx @@ -416,7 +416,8 @@ export function WorkspaceSection({ // Clear the selection clearCardSelection(); - // Note: FolderCard auto-focuses the title when name is "New Folder" + // Navigate to the newly created folder + handleCreatedItems([folderId]); }; // Handle PDF upload from BottomActionBar @@ -650,7 +651,14 @@ export function WorkspaceSection({ } } }, - onCreateFolder: () => { if (addItem) addItem("folder"); }, + onCreateFolder: () => { + if (addItem) { + const itemId = addItem("folder"); + if (handleCreatedItems && itemId) { + handleCreatedItems([itemId]); + } + } + }, onUpload: () => handleUploadMenuItemClick(), onAudio: () => openAudioDialog(), onYouTube: () => setShowYouTubeDialog(true), diff --git a/src/hooks/ui/use-reactive-navigation.ts b/src/hooks/ui/use-reactive-navigation.ts index 7a8caf5f..154cd503 100644 --- a/src/hooks/ui/use-reactive-navigation.ts +++ b/src/hooks/ui/use-reactive-navigation.ts @@ -1,28 +1,23 @@ import { useState, useEffect, useCallback } from "react"; -import { useUIStore } from "@/lib/stores/ui-store"; import { useNavigateToItem } from "./use-navigate-to-item"; import type { AgentState } from "@/lib/workspace-state/types"; /** - * Hook to handle navigation and selection after item creation. + * Hook to handle navigation after item creation. * It waits for the item to appear in the workspace state before attempting to scroll to it, * solving race conditions and stale closure issues. */ export function useReactiveNavigation(workspaceState: AgentState) { const [pendingNavigationId, setPendingNavigationId] = useState(null); const navigateToItem = useNavigateToItem(); - const selectMultipleCards = useUIStore((state) => state.selectMultipleCards); const handleCreatedItems = useCallback((createdIds: string[]) => { - // Select the newly created items - selectMultipleCards(createdIds); - // Set pending navigation to trigger in useEffect once item is available in state if (createdIds.length > 0) { setPendingNavigationId(createdIds[0]); } - }, [selectMultipleCards]); + }, []); // Effect to handle navigation once item appears in state useEffect(() => { From 8ee8b1386ea5b4ce42701bbab51c81f287cfea0d Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 19:57:45 -0500 Subject: [PATCH 2/6] small change --- src/components/workspace-canvas/WorkspaceSection.tsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/components/workspace-canvas/WorkspaceSection.tsx b/src/components/workspace-canvas/WorkspaceSection.tsx index 91d9b27b..a1656fcd 100644 --- a/src/components/workspace-canvas/WorkspaceSection.tsx +++ b/src/components/workspace-canvas/WorkspaceSection.tsx @@ -646,17 +646,13 @@ export function WorkspaceSection({ onCreateNote: () => { if (addItem) { const itemId = addItem("note"); - if (handleCreatedItems && itemId) { - handleCreatedItems([itemId]); - } + handleCreatedItems([itemId]); } }, onCreateFolder: () => { if (addItem) { const itemId = addItem("folder"); - if (handleCreatedItems && itemId) { - handleCreatedItems([itemId]); - } + handleCreatedItems([itemId]); } }, onUpload: () => handleUploadMenuItemClick(), @@ -666,9 +662,7 @@ export function WorkspaceSection({ onFlashcards: () => { if (addItem) { const itemId = addItem("flashcard"); - if (handleCreatedItems && itemId) { - handleCreatedItems([itemId]); - } + handleCreatedItems([itemId]); } }, onQuiz: () => { From d4ab59a66bdf2d2c86aab9893a19558715f019d8 Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 21:18:50 -0500 Subject: [PATCH 3/6] splitview fixed --- src/components/modals/CardDetailModal.tsx | 7 ++----- src/components/modals/PDFViewerModal.tsx | 18 +++++------------- .../workspace-canvas/WorkspaceHeader.tsx | 15 +-------------- src/lib/stores/ui-store.ts | 5 +++++ 4 files changed, 13 insertions(+), 32 deletions(-) diff --git a/src/components/modals/CardDetailModal.tsx b/src/components/modals/CardDetailModal.tsx index 170d3264..6c1f33d5 100644 --- a/src/components/modals/CardDetailModal.tsx +++ b/src/components/modals/CardDetailModal.tsx @@ -40,14 +40,13 @@ export function CardDetailModal({ // Since WorkspaceCard now subscribes directly to its own isSelected state, // changing the selection will only re-render the affected card, not all cards const toggleCardSelection = useUIStore((state) => state.toggleCardSelection); - const selectedCardIds = useUIStore((state) => state.selectedCardIds); - // Auto-select card when modal opens + // Auto-select card when modal opens (read selection state imperatively to avoid infinite loops) useEffect(() => { if (!isOpen || !item?.id) return; // Check if card was already selected at the time of opening - const wasAlreadySelected = selectedCardIds.has(item.id); + const wasAlreadySelected = useUIStore.getState().selectedCardIds.has(item.id); // If not already selected, select it now if (!wasAlreadySelected) { @@ -62,8 +61,6 @@ export function CardDetailModal({ return undefined; }, [isOpen, item?.id]); // eslint-disable-line react-hooks/exhaustive-deps - // eslint-disable-next-line react-hooks/exhaustive-deps - // Handle escape key const handleEscape = useCallback( (e: KeyboardEvent) => { diff --git a/src/components/modals/PDFViewerModal.tsx b/src/components/modals/PDFViewerModal.tsx index e523ebc7..acbfb338 100644 --- a/src/components/modals/PDFViewerModal.tsx +++ b/src/components/modals/PDFViewerModal.tsx @@ -1,13 +1,12 @@ "use client"; import { X } from "lucide-react"; -import { useEffect, useMemo } from "react"; +import { useEffect } from "react"; import ItemHeader from "@/components/workspace-canvas/ItemHeader"; import SpotlightModal from "@/components/SpotlightModal"; import { getCardColorCSS, getCardAccentColor, getWhiteTintedColor } from "@/lib/workspace-state/colors"; import type { Item, PdfData } from "@/lib/workspace-state/types"; -import { useUIStore, selectSelectedCardIdsArray } from "@/lib/stores/ui-store"; -import { useShallow } from "zustand/react/shallow"; +import { useUIStore } from "@/lib/stores/ui-store"; import { formatKeyboardShortcut } from "@/lib/utils/keyboard-shortcut"; import { ItemPanelContent } from "@/components/workspace-canvas/ItemPanelContent"; @@ -33,19 +32,12 @@ export function PDFViewerModal({ const setIsChatExpanded = useUIStore((state) => state.setIsChatExpanded); const toggleCardSelection = useUIStore((state) => state.toggleCardSelection); - // Use array selector with shallow comparison to prevent unnecessary re-renders and SSR issues - const selectedCardIdsArray = useUIStore( - useShallow(selectSelectedCardIdsArray) - ); - const selectedCardIds = useMemo(() => new Set(selectedCardIdsArray), [selectedCardIdsArray]); - - // Track whether we selected the card (so we know whether to deselect on cleanup) + // Auto-select card when modal opens (read selection state imperatively to avoid infinite loops) useEffect(() => { - // Only run when modal is open and we have an item if (!isOpen || !item?.id) return; // Check if card was already selected at the time of opening - const wasAlreadySelected = selectedCardIds.has(item.id); + const wasAlreadySelected = useUIStore.getState().selectedCardIds.has(item.id); // If not already selected, select it now (adds it to context) if (!wasAlreadySelected) { @@ -59,7 +51,7 @@ export function PDFViewerModal({ // If it was already selected, don't change anything on cleanup return undefined; - }, [isOpen, item?.id, selectedCardIds, toggleCardSelection]); + }, [isOpen, item?.id]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { const handleEscape = (e: KeyboardEvent) => { diff --git a/src/components/workspace-canvas/WorkspaceHeader.tsx b/src/components/workspace-canvas/WorkspaceHeader.tsx index 8416e4b3..7c945ecc 100644 --- a/src/components/workspace-canvas/WorkspaceHeader.tsx +++ b/src/components/workspace-canvas/WorkspaceHeader.tsx @@ -806,7 +806,7 @@ export default function WorkspaceHeader({ const { toggleWorkspaceSplitView } = useUIStore.getState(); toggleWorkspaceSplitView(); }} - className="h-8 flex items-center justify-center gap-1.5 rounded-md border border-sidebar-border text-muted-foreground hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors cursor-pointer px-3" + className="h-8 flex items-center justify-center gap-1.5 rounded-md border border-sidebar-border text-muted-foreground hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors cursor-pointer px-3 mr-2" aria-label={workspaceSplitViewActive ? "Focus" : "Split View"} > {workspaceSplitViewActive ? ( @@ -837,19 +837,6 @@ export default function WorkspaceHeader({ - - - - - Close - - {setIsChatExpanded ? ( ()( activeFolderId: folderId, openPanelIds: [], maximizedItemId: null, + workspaceSplitViewActive: false, selectedCardIds: newSelectedCardIds, panelAutoSelectedCardIds: new Set(), }; @@ -217,6 +218,7 @@ export const useUIStore = create()( activeFolderId: null, openPanelIds: [], maximizedItemId: null, + workspaceSplitViewActive: false, selectedCardIds: newSelectedCardIds, panelAutoSelectedCardIds: new Set(), }; @@ -236,6 +238,7 @@ export const useUIStore = create()( return { openPanelIds: [], maximizedItemId: null, + workspaceSplitViewActive: false, selectedCardIds: newSelectedCardIds, panelAutoSelectedCardIds: new Set(), }; @@ -288,6 +291,7 @@ export const useUIStore = create()( return { openPanelIds: [], maximizedItemId: null, + workspaceSplitViewActive: false, selectedCardIds: newSelectedCardIds, panelAutoSelectedCardIds: new Set(), }; @@ -512,6 +516,7 @@ export const useUIStore = create()( openPanelIds: [], itemPrompt: null, maximizedItemId: null, + workspaceSplitViewActive: false, showVersionHistory: false, showCreateWorkspaceModal: false, showSheetModal: false, From da3926a9861911ceb0a4c32e7e530c29a43390bd Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 22:06:01 -0500 Subject: [PATCH 4/6] changes --- .../workspace-canvas/SelectionActionBar.tsx | 24 +++++++++---------- .../workspace-canvas/WorkspaceSection.tsx | 6 ++++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/components/workspace-canvas/SelectionActionBar.tsx b/src/components/workspace-canvas/SelectionActionBar.tsx index 71b31440..edc665de 100644 --- a/src/components/workspace-canvas/SelectionActionBar.tsx +++ b/src/components/workspace-canvas/SelectionActionBar.tsx @@ -23,8 +23,8 @@ export default function SelectionActionBar({ return (

{/* Selection count */} - + {isCompactMode ? ( -
- + + {selectedCount} -
+
) : ( `${selectedCount} ${selectedCount === 1 ? 'item' : 'items'} selected` )}
{/* Separator */} -
+
{/* New Folder Button */} @@ -53,7 +53,7 @@ export default function SelectionActionBar({ type="button" onClick={onCreateFolderFromSelection} className={cn( - "inline-flex items-center gap-2 px-2 py-2 rounded-md", + "inline-flex items-center gap-2 px-2 py-2 rounded-md shrink-0", "text-sm font-medium text-amber-400", "bg-amber-500/10 border border-amber-500/20", "hover:bg-amber-500/20 hover:border-amber-500/30", @@ -75,7 +75,7 @@ export default function SelectionActionBar({ type="button" onClick={onMoveSelected} className={cn( - "inline-flex items-center gap-2 px-2 py-2 rounded-md", + "inline-flex items-center gap-2 px-2 py-2 rounded-md shrink-0", "text-sm font-medium text-blue-400", "bg-blue-500/10 border border-blue-500/20", "hover:bg-blue-500/20 hover:border-blue-500/30", @@ -97,7 +97,7 @@ export default function SelectionActionBar({ type="button" onClick={onDeleteSelected} className={cn( - "inline-flex items-center gap-2 px-2 py-2 rounded-md", + "inline-flex items-center gap-2 px-2 py-2 rounded-md shrink-0", "text-sm font-medium text-red-400", "bg-red-500/10 border border-red-500/20", "hover:bg-red-500/20 hover:border-red-500/30", @@ -113,7 +113,7 @@ export default function SelectionActionBar({ {/* Separator before Clear */} -
+
{/* Clear Selection Button */} @@ -122,7 +122,7 @@ export default function SelectionActionBar({ type="button" onClick={onClearSelection} className={cn( - "inline-flex items-center justify-center p-2 rounded-md", + "inline-flex items-center justify-center p-2 rounded-md shrink-0", "text-foreground/60 dark:text-white/60", "hover:text-foreground/90 hover:bg-foreground/5 dark:hover:text-white/90 dark:hover:bg-white/5", "transition-all duration-200" diff --git a/src/components/workspace-canvas/WorkspaceSection.tsx b/src/components/workspace-canvas/WorkspaceSection.tsx index a1656fcd..79d5b115 100644 --- a/src/components/workspace-canvas/WorkspaceSection.tsx +++ b/src/components/workspace-canvas/WorkspaceSection.tsx @@ -1,4 +1,5 @@ import React, { RefObject, useState, useMemo, useCallback } from "react"; +import { useElementWidth } from "@/hooks/use-element-width"; import { useSearchParams } from "next/navigation"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; @@ -164,6 +165,9 @@ export function WorkspaceSection({ const setSelectedActions = useUIStore((state) => state.setSelectedActions); const { data: session } = useSession(); + // Measure container width for responsive SelectionActionBar + const containerWidth = useElementWidth(scrollAreaRef); + // Assistant API for Deep Research action // Note: WorkspaceSection is inside WorkspaceRuntimeProvider in DashboardLayout, so this hook works const aui = useAui(); @@ -692,7 +696,7 @@ export function WorkspaceSection({ onDeleteSelected={handleDeleteRequest} onCreateFolderFromSelection={handleCreateFolderFromSelection} onMoveSelected={handleMoveSelected} - isCompactMode={isItemPanelOpen && isChatExpanded} + isCompactMode={containerWidth !== undefined && containerWidth < 400} /> )} {/* Move To Dialog */} From bdb9d541e6e3c4bec3e932831f10c06fa4427787 Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 22:09:22 -0500 Subject: [PATCH 5/6] changes --- src/components/workspace-canvas/WorkspaceHeader.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/workspace-canvas/WorkspaceHeader.tsx b/src/components/workspace-canvas/WorkspaceHeader.tsx index 7c945ecc..e1b5742d 100644 --- a/src/components/workspace-canvas/WorkspaceHeader.tsx +++ b/src/components/workspace-canvas/WorkspaceHeader.tsx @@ -828,12 +828,12 @@ export default function WorkspaceHeader({ )} - {workspaceSplitViewActive ? "Focus" : "Split View"} + {workspaceSplitViewActive ? "Focus" : "Split"} - {workspaceSplitViewActive ? "Focus on this item" : "Split View"} + {workspaceSplitViewActive ? "Focus on this item" : "Split"} From c3b52363a719c96df2cacc6220670b3832982015 Mon Sep 17 00:00:00 2001 From: 1shCha Date: Tue, 10 Feb 2026 22:45:23 -0500 Subject: [PATCH 6/6] fixed splitview bug --- src/components/workspace-canvas/WorkspaceGrid.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/workspace-canvas/WorkspaceGrid.tsx b/src/components/workspace-canvas/WorkspaceGrid.tsx index 57fa7a66..53cc855a 100644 --- a/src/components/workspace-canvas/WorkspaceGrid.tsx +++ b/src/components/workspace-canvas/WorkspaceGrid.tsx @@ -859,6 +859,7 @@ export function WorkspaceGrid({ `} {mounted && (