feat: add new view options and update keyboard shortcuts for improved navigation
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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={
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user