From 97453803d6b272ab31b3284007d8296606070378 Mon Sep 17 00:00:00 2001 From: Mo Tarbin Date: Sun, 16 Aug 2026 02:53:53 -0400 Subject: [PATCH] feat: add new view options and update keyboard shortcuts for improved navigation --- public/locales/en/common.json | 6 ++ src/search/GlobalSearchContext.jsx | 2 +- src/search/GlobalSearchPalette.jsx | 97 ++++++++++++++----- src/views/Chores/ArchivedTasks.jsx | 3 - src/views/Chores/MyChores.jsx | 12 ++- src/views/Chores/components/SearchBar.jsx | 2 +- .../Chores/hooks/useKeyboardShortcuts.js | 19 ++-- 7 files changed, 99 insertions(+), 42 deletions(-) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 4317f1a..0cdc241 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -61,6 +61,12 @@ "createFilter": "Create a filter", "viewAllTasks": "View all tasks", "viewArchivedTasks": "View archived tasks", + "viewThings": "View things", + "viewLabels": "View labels", + "viewProjects": "View projects", + "viewFilters": "View filters", + "viewActivities": "View activities", + "viewPoints": "View points", "openSettings": "Open settings", "filterTasks": "Show tasks matching “{{query}}”", "filterTasksSubtitle": "Filter the task list" diff --git a/src/search/GlobalSearchContext.jsx b/src/search/GlobalSearchContext.jsx index eabc6ed..1bf932d 100644 --- a/src/search/GlobalSearchContext.jsx +++ b/src/search/GlobalSearchContext.jsx @@ -152,7 +152,7 @@ export const GlobalSearchProvider = ({ children }) => { useEffect(() => { const onKeyDown = event => { - if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'f') { + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') { event.preventDefault() isOpen ? closeSearch() : openSearch() } diff --git a/src/search/GlobalSearchPalette.jsx b/src/search/GlobalSearchPalette.jsx index a7963f2..1a96625 100644 --- a/src/search/GlobalSearchPalette.jsx +++ b/src/search/GlobalSearchPalette.jsx @@ -1,6 +1,8 @@ import { AddRounded, + ArchiveOutlined, CheckCircleOutline, + FilterAltOutlined, FolderOutlined, HistoryRounded, InboxOutlined, @@ -8,6 +10,8 @@ import { PersonOutline, SearchRounded, SettingsOutlined, + TollOutlined, + WidgetsOutlined, } from '@mui/icons-material' import { Box, @@ -85,30 +89,77 @@ const buildQuickActions = t => [ keywords: 'new filter view saved search add create', route: '/filters?create=1', }, - { - id: 'action:tasks', + // Every destination in the nav drawer is reachable from here, so the palette + // is a complete way to move around the app without opening the drawer. + ...[ + { + id: 'action:tasks', + title: t('search.actions.viewAllTasks'), + keywords: 'tasks chores list all open', + route: '/chores', + icon: , + }, + { + id: 'action:archived', + title: t('search.actions.viewArchivedTasks'), + keywords: 'archive archived tasks completed open', + route: '/archived', + icon: , + }, + { + id: 'action:things', + title: t('search.actions.viewThings'), + keywords: 'things devices sensors trackers state open', + route: '/things', + icon: , + }, + { + id: 'action:labels', + title: t('search.actions.viewLabels'), + keywords: 'labels tags open', + route: '/labels', + icon: , + }, + { + id: 'action:projects', + title: t('search.actions.viewProjects'), + keywords: 'projects folders groups open', + route: '/projects', + icon: , + }, + { + id: 'action:filters', + title: t('search.actions.viewFilters'), + keywords: 'filters saved views open', + route: '/filters', + icon: , + }, + { + id: 'action:activities', + title: t('search.actions.viewActivities'), + keywords: 'activities history timeline log open', + route: '/activities', + icon: , + }, + { + id: 'action:points', + title: t('search.actions.viewPoints'), + keywords: 'points rewards score leaderboard open', + route: '/points', + icon: , + }, + { + id: 'action:settings', + title: t('search.actions.openSettings'), + keywords: 'settings preferences configuration open', + route: '/settings', + icon: , + }, + ].map(action => ({ + ...action, provider: 'actions', - title: t('search.actions.viewAllTasks'), subtitle: t('search.actions.navigation'), - keywords: 'tasks chores list open', - route: '/chores', - }, - { - id: 'action:archived', - provider: 'actions', - title: t('search.actions.viewArchivedTasks'), - subtitle: t('search.actions.navigation'), - keywords: 'archive archived tasks open', - route: '/archived', - }, - { - id: 'action:settings', - provider: 'actions', - title: t('search.actions.openSettings'), - subtitle: t('search.actions.navigation'), - keywords: 'settings preferences configuration open', - route: '/settings', - }, + })), ] const readRecents = () => { @@ -464,7 +515,7 @@ const GlobalSearchPalette = ({ - {ICONS[result.provider]} + {result.icon || ICONS[result.provider]} { padding: 1, }} onChange={handleSearchChange} - startDecorator={ - showKeyboardShortcuts ? : null - } endDecorator={ searchTerm && ( diff --git a/src/views/Chores/MyChores.jsx b/src/views/Chores/MyChores.jsx index d04a303..28ca951 100644 --- a/src/views/Chores/MyChores.jsx +++ b/src/views/Chores/MyChores.jsx @@ -1543,18 +1543,22 @@ const MyChores = () => { onClick={() => { Navigate(`/chores/create`) }} - title='Create new chore (Cmd+C)' + title='Create new chore' > { diff --git a/src/views/Chores/components/SearchBar.jsx b/src/views/Chores/components/SearchBar.jsx index 0ccce0e..156d1c2 100644 --- a/src/views/Chores/components/SearchBar.jsx +++ b/src/views/Chores/components/SearchBar.jsx @@ -43,7 +43,7 @@ const SearchBar = ({ startDecorator={ - + } endDecorator={ diff --git a/src/views/Chores/hooks/useKeyboardShortcuts.js b/src/views/Chores/hooks/useKeyboardShortcuts.js index ecb0cd6..52facb8 100644 --- a/src/views/Chores/hooks/useKeyboardShortcuts.js +++ b/src/views/Chores/hooks/useKeyboardShortcuts.js @@ -23,17 +23,16 @@ export const useKeyboardShortcuts = ({ const isHoldingCmdOrCtrl = event.ctrlKey || event.metaKey - if (isHoldingCmdOrCtrl && event.key === 'k') { + // Cmd/Ctrl + J opens the quick-add modal, + Shift opens the full create + // page. Cmd/Ctrl + K is reserved for global search and handled by + // GlobalSearchContext. + if (isHoldingCmdOrCtrl && event.key.toLowerCase() === 'j') { event.preventDefault() - handlers.onOpenTaskModal() - return - } - - if (addTaskModalOpen) return - - if (isHoldingCmdOrCtrl && event.key === 'j') { - event.preventDefault() - handlers.onNavigateToCreate() + if (event.shiftKey) { + handlers.onNavigateToCreate() + } else { + handlers.onOpenTaskModal() + } return } else if (isHoldingCmdOrCtrl && event.key === 'x') { event.preventDefault()