From 33a4705f95fe1873ab32174c2411d3cc726fb73c Mon Sep 17 00:00:00 2001 From: Daniel Arroyo Date: Sun, 22 Mar 2026 20:22:57 -0300 Subject: [PATCH] feat: MVP-4 P2 - Preload notes on hover - Add prefetchNote function in useNoteListKeyboard hook - Prefetch note pages when navigating with arrow keys - Add hover prefetch in NoteCard using router.prefetch - Update KeyboardNavigableNoteList to use prefetchNote --- .../keyboard-navigable-note-list.tsx | 2 +- src/components/note-card.tsx | 14 +++++++-- src/hooks/use-note-list-keyboard.ts | 29 ++++++++++++++----- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/components/keyboard-navigable-note-list.tsx b/src/components/keyboard-navigable-note-list.tsx index 45678ca..7a1310d 100644 --- a/src/components/keyboard-navigable-note-list.tsx +++ b/src/components/keyboard-navigable-note-list.tsx @@ -47,7 +47,7 @@ export function KeyboardNavigableNoteList({ } }, []) - const { selectedIndex } = useNoteListKeyboard({ + const { selectedIndex, prefetchNote } = useNoteListKeyboard({ notes, onEdit, onFavorite: handleFavorite, diff --git a/src/components/note-card.tsx b/src/components/note-card.tsx index 18db59d..2f760b7 100644 --- a/src/components/note-card.tsx +++ b/src/components/note-card.tsx @@ -1,6 +1,7 @@ 'use client' import Link from 'next/link' +import { useRouter } from 'next/navigation' import { Note } from '@/types/note' import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' @@ -16,12 +17,21 @@ const typeColors: Record = { } export function NoteCard({ note }: { note: Note }) { + const router = useRouter() const preview = note.content.slice(0, 100) + (note.content.length > 100 ? '...' : '') const typeColor = typeColors[note.type] || typeColors.note + const handleMouseEnter = () => { + // Prefetch on hover for faster navigation + router.prefetch(`/notes/${note.id}`) + } + return ( - - + +

{note.title}

diff --git a/src/hooks/use-note-list-keyboard.ts b/src/hooks/use-note-list-keyboard.ts index a651f2c..fb333e2 100644 --- a/src/hooks/use-note-list-keyboard.ts +++ b/src/hooks/use-note-list-keyboard.ts @@ -1,4 +1,4 @@ -import { useEffect, useCallback, useState } from 'react' +import { useEffect, useCallback, useState, useRef } from 'react' import { useRouter } from 'next/navigation' import { Note } from '@/types/note' @@ -17,10 +17,19 @@ export function useNoteListKeyboard({ }: UseNoteListKeyboardOptions) { const [selectedIndex, setSelectedIndex] = useState(-1) const router = useRouter() + const prefetchedRef = useRef>(new Set()) + + // Prefetch a note's page data for faster navigation + const prefetchNote = useCallback((noteId: string) => { + if (prefetchedRef.current.has(noteId)) return + prefetchedRef.current.add(noteId) + router.prefetch(`/notes/${noteId}`) + }, [router]) // Reset selection when notes change useEffect(() => { setSelectedIndex(-1) + prefetchedRef.current.clear() }, [notes.length]) const handleKeyDown = useCallback( @@ -38,13 +47,19 @@ export function useNoteListKeyboard({ switch (e.key) { case 'ArrowDown': e.preventDefault() - setSelectedIndex((prev) => - prev < notes.length - 1 ? prev + 1 : notes.length - 1 - ) + setSelectedIndex((prev) => { + const next = prev < notes.length - 1 ? prev + 1 : notes.length - 1 + if (notes[next]) prefetchNote(notes[next].id) + return next + }) break case 'ArrowUp': e.preventDefault() - setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1)) + setSelectedIndex((prev) => { + const next = prev > 0 ? prev - 1 : -1 + if (next >= 0 && notes[next]) prefetchNote(notes[next].id) + return next + }) break case 'Enter': e.preventDefault() @@ -75,7 +90,7 @@ export function useNoteListKeyboard({ break } }, - [notes, selectedIndex, router, onEdit, onFavorite, onPin] + [notes, selectedIndex, router, onEdit, onFavorite, onPin, prefetchNote] ) useEffect(() => { @@ -83,5 +98,5 @@ export function useNoteListKeyboard({ return () => window.removeEventListener('keydown', handleKeyDown) }, [handleKeyDown]) - return { selectedIndex, setSelectedIndex } + return { selectedIndex, setSelectedIndex, prefetchNote } }