feat: add new view options and update keyboard shortcuts for improved navigation

This commit is contained in:
Mo Tarbin
2026-08-16 02:53:53 -04:00
parent 1c99bd1886
commit 97453803d6
7 changed files with 99 additions and 42 deletions

View File

@@ -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"

View File

@@ -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()
}

View File

@@ -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: <InboxOutlined />,
},
{
id: 'action:archived',
title: t('search.actions.viewArchivedTasks'),
keywords: 'archive archived tasks completed open',
route: '/archived',
icon: <ArchiveOutlined />,
},
{
id: 'action:things',
title: t('search.actions.viewThings'),
keywords: 'things devices sensors trackers state open',
route: '/things',
icon: <WidgetsOutlined />,
},
{
id: 'action:labels',
title: t('search.actions.viewLabels'),
keywords: 'labels tags open',
route: '/labels',
icon: <LabelOutlined />,
},
{
id: 'action:projects',
title: t('search.actions.viewProjects'),
keywords: 'projects folders groups open',
route: '/projects',
icon: <FolderOutlined />,
},
{
id: 'action:filters',
title: t('search.actions.viewFilters'),
keywords: 'filters saved views open',
route: '/filters',
icon: <FilterAltOutlined />,
},
{
id: 'action:activities',
title: t('search.actions.viewActivities'),
keywords: 'activities history timeline log open',
route: '/activities',
icon: <HistoryRounded />,
},
{
id: 'action:points',
title: t('search.actions.viewPoints'),
keywords: 'points rewards score leaderboard open',
route: '/points',
icon: <TollOutlined />,
},
{
id: 'action:settings',
title: t('search.actions.openSettings'),
keywords: 'settings preferences configuration open',
route: '/settings',
icon: <SettingsOutlined />,
},
].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 = ({
<ListItemDecorator
sx={{ mt: 0.25, color: result.color || 'text.secondary' }}
>
{ICONS[result.provider]}
{result.icon || ICONS[result.provider]}
</ListItemDecorator>
<ListItemContent>
<Typography

View File

@@ -752,9 +752,6 @@ const ArchivedTasks = () => {
padding: 1,
}}
onChange={handleSearchChange}
startDecorator={
showKeyboardShortcuts ? <KeyboardShortcutHint shortcut='F' /> : null
}
endDecorator={
searchTerm && (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>

View File

@@ -1543,18 +1543,22 @@ const MyChores = () => {
onClick={() => {
Navigate(`/chores/create`)
}}
title='Create new chore (Cmd+C)'
title='Create new chore'
>
<Add />
<KeyboardShortcutHint
sx={{
position: 'absolute',
top: -8,
right: -8,
top: -12,
// Anchored left so the wider "⌘ + Shift + J" label grows to the
// right instead of off the left edge of the viewport.
left: 2,
whiteSpace: 'nowrap',
zIndex: 1000,
}}
show={showKeyboardShortcuts}
shortcut='J'
withShift
/>
</IconButton>
<IconButton
@@ -1583,7 +1587,7 @@ const MyChores = () => {
<KeyboardShortcutHint
sx={{ position: 'relative', left: -40, top: 30 }}
show={showKeyboardShortcuts}
shortcut='K'
shortcut='J'
/>
</Box>
<NotificationAccessSnackbar />

View File

@@ -43,7 +43,7 @@ const SearchBar = ({
startDecorator={
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>
<SearchRounded sx={{ fontSize: 18, color: 'text.secondary' }} />
<KeyboardShortcutHint shortcut='F' show={showKeyboardShortcuts} />
<KeyboardShortcutHint shortcut='K' show={showKeyboardShortcuts} />
</Box>
}
endDecorator={

View File

@@ -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()