11import { Link } from "@tanstack/react-router" ;
22import { clsx } from "clsx" ;
3- import { ChartNoAxesGantt , FolderOpenIcon } from "lucide-react" ;
3+ import { ChartNoAxesGantt , FolderOpenIcon , PanelLeftCloseIcon , SearchIcon } from "lucide-react" ;
44import { useState } from "react" ;
55import { useCell , useRowIds , useSliceRowIds } from "tinybase/ui-react" ;
66
77import * as persisted from "../../tinybase/store/persisted" ;
88
99import { ContextMenuItem } from "@hypr/ui/components/ui/context-menu" ;
1010import { Tabs , TabsContent , TabsList , TabsTrigger } from "@hypr/ui/components/ui/tabs" ;
11+ import { useLeftSidebar } from "@hypr/utils/contexts" ;
1112import { useTabs } from "../../hooks/useTabs" ;
1213import { Tab } from "../../types" ;
1314import { InteractiveButton } from "../interactive-button" ;
1415
1516export function LeftSidebar ( ) {
17+ const { togglePanel : toggleLeftPanel } = useLeftSidebar ( ) ;
18+
1619 return (
17- < div className = "h-screen border-r w-[300px] " >
18- < Tabs defaultValue = "timeline" >
20+ < div className = "h-full border-r w-full flex flex-col overflow-hidden " >
21+ < Tabs defaultValue = "timeline" className = "flex flex-col flex-1 overflow-hidden" >
1922 < TabsList
2023 data-tauri-drag-region
2124 className = { clsx ( [
22- "h-full flex flex-row" ,
25+ "flex flex-row shrink-0 " ,
2326 "flex w-full items-center justify-between min-h-11 py-1 px-2 border-b" ,
2427 "border-border bg-neutral-50" ,
2528 "pl-[72px]" ,
@@ -31,14 +34,32 @@ export function LeftSidebar() {
3134 < TabsTrigger value = "timeline" className = "flex-1" >
3235 < ChartNoAxesGantt />
3336 </ TabsTrigger >
37+ < TabsTrigger value = "search" className = "flex-1" >
38+ < SearchIcon />
39+ </ TabsTrigger >
40+
41+ < PanelLeftCloseIcon
42+ onClick = { toggleLeftPanel }
43+ className = "cursor-pointer h-5 w-5"
44+ />
3445 </ TabsList >
3546
36- < TabsContent value = "timeline" className = "flex-1 overflow-auto p-2 mt-0" >
37- < TimelineView />
47+ < TabsContent value = "timeline" className = "flex-1 mt-0 h-0" >
48+ < div className = "h-full overflow-y-auto p-2" >
49+ < TimelineView />
50+ </ div >
51+ </ TabsContent >
52+
53+ < TabsContent value = "folder" className = "flex-1 mt-0 h-0" >
54+ < div className = "h-full overflow-y-auto p-2" >
55+ < FolderView />
56+ </ div >
3857 </ TabsContent >
3958
40- < TabsContent value = "folder" className = "flex-1 overflow-auto p-2 mt-0" >
41- < FolderView />
59+ < TabsContent value = "search" className = "flex-1 mt-0 h-0" >
60+ < div className = "h-full flex flex-col overflow-hidden" >
61+ < SearchView />
62+ </ div >
4263 </ TabsContent >
4364 </ Tabs >
4465 </ div >
@@ -47,29 +68,53 @@ export function LeftSidebar() {
4768
4869function TimelineView ( ) {
4970 const allSessionIds = useRowIds ( "sessions" , persisted . STORE_ID ) ;
71+ const { currentTab } = useTabs ( ) ;
5072
5173 return (
5274 < div className = "flex flex-col" >
53- { allSessionIds ?. map ( ( sessionId ) => < SessionItem key = { sessionId } sessionId = { sessionId } /> ) }
75+ { allSessionIds ?. map ( ( sessionId ) => (
76+ < SessionItem key = { sessionId } sessionId = { sessionId } active = { currentTab ?. id === sessionId } />
77+ ) ) }
5478 </ div >
5579 ) ;
5680}
5781
82+ function SearchView ( ) {
83+ return (
84+ < >
85+ < div className = "sticky top-0 bg-white z-10 p-2 border-b" >
86+ < input
87+ type = "text"
88+ placeholder = "Search..."
89+ className = "w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
90+ />
91+ </ div >
92+ < div className = "flex-1 overflow-y-auto p-2" >
93+ { /* Search results will go here */ }
94+ </ div >
95+ </ >
96+ ) ;
97+ }
98+
5899function FolderView ( ) {
59100 const rootFolderIds = useSliceRowIds ( persisted . INDEXES . foldersByParent , "" , persisted . STORE_ID ) ;
60101 const rootSessionIds = useSliceRowIds ( persisted . INDEXES . sessionsByFolder , "" , persisted . STORE_ID ) ;
102+ const { currentTab } = useTabs ( ) ;
61103
62104 return (
63105 < div className = "flex flex-col" >
64106 { rootFolderIds ?. map ( ( folderId ) => < FolderTreeItem key = { folderId } folderId = { folderId } /> ) }
65-
66- { rootSessionIds ?. map ( ( sessionId ) => < SessionItemNested key = { sessionId } sessionId = { sessionId } depth = { 0 } /> ) }
107+ { rootSessionIds ?. map ( ( sessionId ) => (
108+ < SessionItemNested key = { sessionId } sessionId = { sessionId } depth = { 0 } active = { currentTab ?. id === sessionId } />
109+ ) ) }
67110 </ div >
68111 ) ;
69112}
70113
71114function FolderTreeItem ( { folderId, depth = 0 } : { folderId : string ; depth ?: number } ) {
72115 const [ isOpen , setIsOpen ] = useState ( true ) ;
116+ const { currentTab } = useTabs ( ) ;
117+
73118 const name = useCell ( "folders" , folderId , "name" , persisted . STORE_ID ) ;
74119 const sessionIds = useSliceRowIds ( persisted . INDEXES . sessionsByFolder , folderId , persisted . STORE_ID ) ;
75120 const subFolderIds = useSliceRowIds ( persisted . INDEXES . foldersByParent , folderId , persisted . STORE_ID ) ;
@@ -92,7 +137,12 @@ function FolderTreeItem({ folderId, depth = 0 }: { folderId: string; depth?: num
92137 { isOpen && (
93138 < >
94139 { sessionIds ?. map ( ( sessionId ) => (
95- < SessionItemNested key = { sessionId } sessionId = { sessionId } depth = { depth + 1 } />
140+ < SessionItemNested
141+ key = { sessionId }
142+ sessionId = { sessionId }
143+ depth = { depth + 1 }
144+ active = { currentTab ?. id === sessionId }
145+ />
96146 ) ) }
97147
98148 { subFolderIds ?. map ( ( subId ) => < FolderTreeItem key = { subId } folderId = { subId } depth = { depth + 1 } /> ) }
0 commit comments