feat(ui): panneau repliable, carnets plus lisibles et accueil plus clair

Harmonise la liste des notes et l’éditeur (titres, dates, retour),
rend la saisie rapide et les raccourcis de l’accueil utilisables
sur téléphone, et conserve le panneau latéral repliable.
This commit is contained in:
Antigravity
2026-09-05 20:53:48 +00:00
parent a7b16870a4
commit 3bdbec575a
37 changed files with 1138 additions and 482 deletions

View File

@@ -16,6 +16,7 @@ import {
Loader2,
} from 'lucide-react'
import { useRouter } from 'next/navigation'
import { consumeRememberedSearchQuery, rememberSearchQuery } from '@/lib/search/restore-search'
import { useNotebooks } from '@/context/notebooks-context'
import { useLanguage } from '@/lib/i18n'
import type { Note } from '@/lib/types'
@@ -89,9 +90,12 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
useEffect(() => {
if (isOpen) {
setTimeout(() => inputRef.current?.focus(), 50)
setQuery('')
setResults([])
setSelectedIndex(0)
const restored = consumeRememberedSearchQuery()
setQuery(restored)
if (!restored) {
setResults([])
setSelectedIndex(0)
}
}
}, [isOpen])
@@ -111,6 +115,18 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
[notebooks]
)
const openNoteFromSearch = useCallback((noteId: string) => {
rememberSearchQuery(query)
const onHome = typeof window !== 'undefined' && window.location.pathname === '/home'
const params = onHome
? new URLSearchParams(window.location.search)
: new URLSearchParams()
params.set('openNote', noteId)
params.set('from', 'search')
router.push(`/home?${params.toString()}`)
onClose()
}, [query, router, onClose])
// Fetch notes from API with debounce
useEffect(() => {
if (debounceRef.current) clearTimeout(debounceRef.current)
@@ -393,14 +409,13 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
else if (e.key === 'Enter') {
e.preventDefault()
if (filteredMatches[selectedIndex]) {
router.push(`/home?openNote=${filteredMatches[selectedIndex].noteId}`)
onClose()
openNoteFromSearch(filteredMatches[selectedIndex].noteId)
}
}
}
window.addEventListener('keydown', handleKeyDown)
return () => window.removeEventListener('keydown', handleKeyDown)
}, [isOpen, selectedIndex, filteredMatches, onClose, router])
}, [isOpen, selectedIndex, filteredMatches, onClose, openNoteFromSearch])
// Save/remove query from localStorage
const handleSaveQuery = () => {
@@ -587,8 +602,7 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
key={m.id}
onClick={() => setSelectedIndex(idx)}
onDoubleClick={() => {
router.push(`/home?openNote=${m.noteId}`)
onClose()
openNoteFromSearch(m.noteId)
}}
className={`p-2.5 rounded-xl cursor-pointer text-left select-none relative flex flex-col gap-1 border transition-all ${
isSelected
@@ -676,8 +690,7 @@ export function SearchModal({ isOpen, onClose }: SearchModalProps) {
<div className="pt-4 border-t border-border/40 dark:border-zinc-800 flex items-center justify-between shrink-0 mt-3">
<button
onClick={() => {
router.push(`/home?openNote=${activeMatch.noteId}`)
onClose()
openNoteFromSearch(activeMatch.noteId)
}}
className="px-5 py-2.5 bg-brand-accent text-white hover:bg-brand-accent/90 text-xs font-semibold rounded-xl flex items-center gap-2 transition-all shadow-sm"
>