feat: add sidebar collapse, category/tag filtering, and workspace CRUD (Phase D)

- Sidebar collapse/expand toggle with icon-only rail mode (persisted)
- Sidebar category/tag clicks navigate to /trees with URL params
- TreeLibraryPage syncs filters from URL search params bidirectionally
- Workspace create modal with icon picker and auto-slug generation
- TopBar logo adapts to collapsed sidebar state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-15 05:05:25 -05:00
parent 09cd05e143
commit f334ba861b
9 changed files with 301 additions and 40 deletions

View File

@@ -6,15 +6,18 @@ interface WorkspaceState {
workspaces: Workspace[]
activeWorkspaceId: string | null
loading: boolean
sidebarCollapsed: boolean
setActiveWorkspace: (id: string) => void
fetchWorkspaces: () => Promise<void>
getActiveWorkspace: () => Workspace | undefined
toggleSidebar: () => void
}
export const useWorkspaceStore = create<WorkspaceState>((set, get) => ({
workspaces: [],
activeWorkspaceId: localStorage.getItem('active-workspace-id'),
loading: false,
sidebarCollapsed: localStorage.getItem('sidebar-collapsed') === 'true',
setActiveWorkspace: (id: string) => {
localStorage.setItem('active-workspace-id', id)
@@ -47,4 +50,10 @@ export const useWorkspaceStore = create<WorkspaceState>((set, get) => ({
const { workspaces, activeWorkspaceId } = get()
return workspaces.find(w => w.id === activeWorkspaceId)
},
toggleSidebar: () => {
const next = !get().sidebarCollapsed
localStorage.setItem('sidebar-collapsed', String(next))
set({ sidebarCollapsed: next })
},
}))