Next/previous keyboard navigation for home

This commit is contained in:
Jackson Harper
2024-07-09 19:58:13 +08:00
parent c19c946474
commit a536b21c64

View File

@ -29,11 +29,13 @@ import { useGetViewerQuery } from '../../lib/networking/queries/useGetViewerQuer
import useLibraryItemActions from '../../lib/hooks/useLibraryItemActions'
import { SyncLoader } from 'react-spinners'
import { useGetLibraryItemsQuery } from '../../lib/networking/queries/useGetLibraryItemsQuery'
import { useRegisterActions } from 'kbar'
export function HomeContainer(): JSX.Element {
const router = useRouter()
const homeData = useGetHomeItems()
const { viewerData } = useGetViewerQuery()
const [selectedItem, setSelectedItem] = useState<HTMLElement | null>(null)
useApplyLocalTheme()
@ -62,6 +64,130 @@ export function HomeContainer(): JSX.Element {
)
}
const moveSelection = useCallback(
(direction: 'next' | 'previous') => {
const elements =
document.querySelectorAll<HTMLElement>('[data-navigable]')
let index = Array.prototype.indexOf.call(elements, selectedItem)
if (direction == 'next') {
index = index === -1 ? 0 : Math.min(index + 1, elements.length - 1)
} else if (direction == 'previous') {
index = index === -1 ? 0 : Math.max(index - 1, 0)
}
console.log('elements: ', index, elements)
const selected = elements[index]
setSelectedItem(selected)
selected.focus()
},
[selectedItem, setSelectedItem]
)
useRegisterActions(
[
{
id: 'open_readable',
section: 'Items',
name: 'Open focused item',
shortcut: ['enter'],
keywords: 'open',
perform: () => {
console.log('open item')
},
},
{
id: 'open_original',
section: 'Items',
name: 'Open original url',
shortcut: ['o'],
keywords: 'open original',
perform: () => {
console.log('open original')
},
},
{
id: 'archive',
section: 'Items',
name: 'Archive item',
shortcut: ['e'],
keywords: 'archive item',
perform: () => {
console.log('archive')
},
},
{
id: 'mark_read',
section: 'Items',
name: 'Mark item as read',
shortcut: ['-'],
keywords: 'mark read',
perform: () => {
console.log('mark_read')
},
},
{
id: 'delete_item',
section: 'Items',
name: 'Delete item',
shortcut: ['#'],
keywords: 'delete remove',
perform: () => {
console.log('delete')
},
},
{
id: 'move_next',
section: 'Items',
name: 'Focus next item',
shortcut: ['arrowdown'],
keywords: 'move next',
perform: () => {
moveSelection('next')
},
},
{
id: 'move_previous',
section: 'Items',
name: 'Focus previous item',
shortcut: ['arrowup'],
keywords: 'move previous',
perform: () => {
moveSelection('previous')
},
},
{
id: 'move_next_vim',
section: 'Items',
name: 'Focus next item',
shortcut: ['j'],
keywords: 'move next',
perform: () => {
moveSelection('next')
},
},
{
id: 'move_previous_vim',
section: 'Items',
name: 'Focus previous item',
shortcut: ['k'],
keywords: 'move previous',
perform: () => {
moveSelection('previous')
},
},
// {
// shortcutKeys: ['a'],
// actionDescription: 'Open Add Link dialog',
// shortcutKeyDescription: 'a',
// callback: () => actionHandler('showAddLinkModal'),
// },
],
[selectedItem]
)
return (
<VStack
distribution="start"
@ -106,7 +232,7 @@ export function HomeContainer(): JSX.Element {
)
case 'top_picks':
if (homeSection.items.length < 1) {
return <FromYourLibraryHomeSection />
return <FromYourLibraryHomeSection key="section-from-your" />
}
return (
<TopPicksHomeSection
@ -402,8 +528,6 @@ const FromYourLibraryHomeSection = (): JSX.Element => {
})
}, [searchItems])
console.log('items: ', items)
return (
<VStack
distribution="start"
@ -742,6 +866,8 @@ const TopPicksItemView = (
return (
<VStack
tabIndex={0}
data-navigable={props.homeItem.id}
css={{
width: '100%',
pt: '15px',
@ -750,6 +876,13 @@ const TopPicksItemView = (
'@mdDown': {
borderRadius: '0px',
},
'&:focus-visible': {
outline: 'none',
bg: '$homeCardHover',
},
'&:focus-visible .title-text': {
textDecoration: 'underline',
},
'&:hover': {
bg: '$homeCardHover',
},
@ -900,6 +1033,7 @@ const QuickLinkHomeItemView = (props: HomeItemViewProps): JSX.Element => {
return (
<VStack
data-navigable={props.homeItem.id}
css={{
mt: '10px',
width: '100%',