11import { Command } from "@features/command/components/Command" ;
22import { CommandKeyHints } from "@features/command/components/CommandKeyHints" ;
3- import { useTasks } from "@features/tasks/hooks/useTasks" ;
4- import { FileTextIcon , ListBulletIcon } from "@radix-ui/react-icons" ;
3+ import { useRightSidebarStore } from "@features/right-sidebar" ;
4+ import { useSidebarStore } from "@features/sidebar/stores/sidebarStore" ;
5+ import {
6+ FileTextIcon ,
7+ GearIcon ,
8+ HomeIcon ,
9+ MoonIcon ,
10+ SunIcon ,
11+ ViewVerticalIcon ,
12+ } from "@radix-ui/react-icons" ;
513import { Flex , Text } from "@radix-ui/themes" ;
6- import type { Task } from "@shared/types" ;
714import { useNavigationStore } from "@stores/navigationStore" ;
8- import { useCallback , useEffect , useRef } from "react" ;
15+ import { useRegisteredFoldersStore } from "@stores/registeredFoldersStore" ;
16+ import { useThemeStore } from "@stores/themeStore" ;
17+ import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
918import { useHotkeys } from "react-hotkeys-hook" ;
1019
1120interface CommandMenuProps {
@@ -14,38 +23,52 @@ interface CommandMenuProps {
1423}
1524
1625export function CommandMenu ( { open, onOpenChange } : CommandMenuProps ) {
17- const { navigateToTaskList, navigateToTask, navigateToTaskInput } =
18- useNavigationStore ( ) ;
19- const { data : tasks = [ ] } = useTasks ( ) ;
26+ const { navigateToTaskInput, navigateToSettings } = useNavigationStore ( ) ;
27+ const { folders } = useRegisteredFoldersStore ( ) ;
28+ const { isDarkMode, toggleDarkMode } = useThemeStore ( ) ;
29+ const toggleLeftSidebar = useSidebarStore ( ( state ) => state . toggle ) ;
30+ const toggleRightSidebar = useRightSidebarStore ( ( state ) => state . toggle ) ;
2031 const commandRef = useRef < HTMLDivElement > ( null ) ;
32+ const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
2133
22- // Close handlers
23- const handleClose = useCallback ( ( ) => {
24- onOpenChange ( false ) ;
25- } , [ onOpenChange ] ) ;
34+ const close = useCallback ( ( ) => onOpenChange ( false ) , [ onOpenChange ] ) ;
2635
27- useHotkeys ( "escape" , handleClose , {
36+ const runAndClose = useCallback (
37+ < T extends unknown [ ] > ( fn : ( ...args : T ) => void ) =>
38+ ( ...args : T ) => {
39+ fn ( ...args ) ;
40+ close ( ) ;
41+ } ,
42+ [ close ] ,
43+ ) ;
44+
45+ useEffect ( ( ) => {
46+ if ( ! open ) {
47+ setSearchQuery ( "" ) ;
48+ }
49+ } , [ open ] ) ;
50+
51+ useHotkeys ( "escape" , close , {
2852 enabled : open ,
2953 enableOnContentEditable : true ,
3054 enableOnFormTags : true ,
3155 preventDefault : true ,
3256 } ) ;
3357
34- useHotkeys ( "mod+k" , handleClose , {
58+ useHotkeys ( "mod+k" , close , {
3559 enabled : open ,
3660 enableOnContentEditable : true ,
3761 enableOnFormTags : true ,
3862 preventDefault : true ,
3963 } ) ;
4064
41- useHotkeys ( "mod+p" , handleClose , {
65+ useHotkeys ( "mod+p" , close , {
4266 enabled : open ,
4367 enableOnContentEditable : true ,
4468 enableOnFormTags : true ,
4569 preventDefault : true ,
4670 } ) ;
4771
48- // Handle click outside
4972 useEffect ( ( ) => {
5073 if ( ! open ) return ;
5174
@@ -54,30 +77,21 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
5477 commandRef . current &&
5578 ! commandRef . current . contains ( event . target as Node )
5679 ) {
57- onOpenChange ( false ) ;
80+ close ( ) ;
5881 }
5982 } ;
6083
6184 document . addEventListener ( "mousedown" , handleClickOutside ) ;
62- return ( ) => {
63- document . removeEventListener ( "mousedown" , handleClickOutside ) ;
64- } ;
65- } , [ open , onOpenChange ] ) ;
66-
67- const handleNavigateToTasks = ( ) => {
68- navigateToTaskList ( ) ;
69- onOpenChange ( false ) ;
70- } ;
71-
72- const handleCreateTask = ( ) => {
73- navigateToTaskInput ( ) ;
74- onOpenChange ( false ) ;
75- } ;
85+ return ( ) => document . removeEventListener ( "mousedown" , handleClickOutside ) ;
86+ } , [ open , close ] ) ;
7687
77- const handleNavigateToTaskClick = ( task : Task ) => {
78- navigateToTask ( task ) ;
79- onOpenChange ( false ) ;
80- } ;
88+ const matchingFolders = useMemo ( ( ) => {
89+ if ( ! searchQuery . trim ( ) ) return [ ] ;
90+ const query = searchQuery . toLowerCase ( ) ;
91+ return folders . filter ( ( folder ) =>
92+ folder . name . toLowerCase ( ) . includes ( query ) ,
93+ ) ;
94+ } , [ folders , searchQuery ] ) ;
8195
8296 if ( ! open ) return null ;
8397
@@ -95,53 +109,81 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
95109 < Command . Root className = "min-h-0 flex-1" >
96110 < div className = "flex items-center border-gray-6 border-b px-3" >
97111 < Command . Input
98- placeholder = "Search for tasks, navigate to sections ..."
112+ placeholder = "Search commands ..."
99113 autoFocus = { true }
100114 style = { { fontSize : "12px" } }
101115 className = "w-full bg-transparent py-3 outline-none placeholder:text-gray-9"
116+ onValueChange = { setSearchQuery }
102117 />
103118 </ div >
104119
105120 < Command . List style = { { maxHeight : "400px" } } >
106121 < Command . Empty > No results found.</ Command . Empty >
107122
108- < Command . Group heading = "Actions" >
109- < Command . Item value = "Create new task" onSelect = { handleCreateTask } >
110- < FileTextIcon className = "mr-3 h-3 w-3 text-gray-11" />
111- < Text size = "1" > Create new task</ Text >
123+ < Command . Group heading = "Navigation" >
124+ < Command . Item
125+ value = "Home"
126+ onSelect = { runAndClose ( navigateToTaskInput ) }
127+ >
128+ < HomeIcon className = "mr-3 h-3 w-3 text-gray-11" />
129+ < Text size = "1" > Home</ Text >
130+ </ Command . Item >
131+ < Command . Item
132+ value = "Settings"
133+ onSelect = { runAndClose ( navigateToSettings ) }
134+ >
135+ < GearIcon className = "mr-3 h-3 w-3 text-gray-11" />
136+ < Text size = "1" > Settings</ Text >
112137 </ Command . Item >
113138 </ Command . Group >
114139
115- < Command . Group heading = "Navigation " >
140+ < Command . Group heading = "Actions " >
116141 < Command . Item
117- value = "Go to tasks "
118- onSelect = { handleNavigateToTasks }
142+ value = "Toggle theme dark light mode "
143+ onSelect = { runAndClose ( toggleDarkMode ) }
119144 >
120- < ListBulletIcon className = "mr-3 h-3 w-3 text-gray-11" />
121- < Text size = "1" > Go to tasks</ Text >
145+ { isDarkMode ? (
146+ < SunIcon className = "mr-3 h-3 w-3 text-gray-11" />
147+ ) : (
148+ < MoonIcon className = "mr-3 h-3 w-3 text-gray-11" />
149+ ) }
150+ < Text size = "1" > Toggle theme</ Text >
151+ </ Command . Item >
152+ < Command . Item
153+ value = "Toggle left sidebar"
154+ onSelect = { runAndClose ( toggleLeftSidebar ) }
155+ >
156+ < ViewVerticalIcon className = "mr-3 h-3 w-3 text-gray-11" />
157+ < Text size = "1" > Toggle left sidebar</ Text >
158+ </ Command . Item >
159+ < Command . Item
160+ value = "Toggle right sidebar"
161+ onSelect = { runAndClose ( toggleRightSidebar ) }
162+ >
163+ < ViewVerticalIcon className = "mr-3 h-3 w-3 rotate-180 text-gray-11" />
164+ < Text size = "1" > Toggle right sidebar</ Text >
165+ </ Command . Item >
166+ < Command . Item
167+ value = "Create new task"
168+ onSelect = { runAndClose ( navigateToTaskInput ) }
169+ >
170+ < FileTextIcon className = "mr-3 h-3 w-3 text-gray-11" />
171+ < Text size = "1" > New task</ Text >
122172 </ Command . Item >
123173 </ Command . Group >
124174
125- { tasks . length > 0 && (
126- < Command . Group heading = "Tasks " >
127- { tasks . map ( ( task ) => (
175+ { matchingFolders . length > 0 && (
176+ < Command . Group heading = "New task in folder " >
177+ { matchingFolders . map ( ( folder ) => (
128178 < Command . Item
129- key = { task . id }
130- value = { `${ task . id } ${ task . title } ` }
131- onSelect = { ( ) => handleNavigateToTaskClick ( task ) }
132- className = "items-start"
179+ key = { folder . id }
180+ value = { `New task in ${ folder . name } folder` }
181+ onSelect = { runAndClose ( ( ) => navigateToTaskInput ( folder . id ) ) }
133182 >
134- < FileTextIcon className = "mt-0.5 mr-3 h-4 w-4 flex-shrink-0 text-gray-11" />
135- < Flex direction = "column" flexGrow = "1" className = "min-w-0" >
136- < Text size = "1" weight = "medium" className = "truncate" >
137- { task . title }
138- </ Text >
139- { task . description && (
140- < Text size = "1" color = "gray" className = "mt-1 truncate" >
141- { task . description }
142- </ Text >
143- ) }
144- </ Flex >
183+ < FileTextIcon className = "mr-3 h-3 w-3 text-gray-11" />
184+ < Text size = "1" >
185+ New task in < Text weight = "bold" > { folder . name } </ Text >
186+ </ Text >
145187 </ Command . Item >
146188 ) ) }
147189 </ Command . Group >
0 commit comments