Archived
4.2 KiB
4.2 KiB
Mobile Book Search & Discovery — Spec
Overview
Enhance the existing book search experience with mobile-first features: voice search via the Web Speech API, real-time autocomplete suggestions, and touch-optimized responsive layout.
Prerequisites
- Backend endpoints already exist (from
docs/backend/search-discovery-spec.md):GET /api/books/?q=...&genre=...&author=...&reading_status=...— paginated searchGET /api/books/{id}/— book detailGET /api/books/genres/— genre discoveryGET /api/books/authors/— author discovery
- Frontend
LibraryPageandBookDetailPagecomponents exist but lacked API client methods and types (fixed in this PR).
Frontend API Client Additions
frontend/src/types/book.ts — New exports
export interface BookSearchParams {
q?: string;
genre?: string;
author?: string;
reading_status?: string;
ordering?: string;
page?: number;
page_size?: number;
}
export const READING_STATUS_OPTIONS: { value: string; label: string }[] = [
{ value: "", label: "All Statuses" },
{ value: "want_to_read", label: "Want to Read" },
{ value: "reading", label: "Reading" },
{ value: "finished", label: "Finished" },
{ value: "dnf", label: "Did Not Finish" },
];
frontend/src/api/books.ts — New methods on booksApi
| Method | Endpoint | Returns |
|---|---|---|
searchBooks(params) |
GET /api/books/ |
{ count, results: BookListItem[] } |
getBook(id) |
GET /api/books/{id}/ |
BookDetail |
getGenres() |
GET /api/books/genres/ |
string[] |
getAuthors() |
GET /api/books/authors/ |
string[] |
Mobile Features
1. Voice Search
- Hook:
useVoiceSearchinfrontend/src/hooks/useVoiceSearch.ts - Uses the Web Speech API (
SpeechRecognition/webkitSpeechRecognition) - Returns:
{ isListening, transcript, isSupported, startListening, stopListening, hasError } - Renders a microphone icon button next to the search input
- On mobile, tapping the mic icon triggers the native speech recognition prompt
- On success, populates the search input with the transcript and triggers a search
- Graceful degradation: if SpeechRecognition API is unavailable, the mic button is hidden
2. Real-Time Suggestions (Autocomplete)
- Component:
SearchSuggestionsrendered as a dropdown below the search input - On each keystroke (debounced 200ms), fetches
GET /api/books/?q=...&page_size=5for suggestions - Shows up to 5 book title/author suggestions in a styled dropdown list
- Clicking a suggestion navigates directly to
/books/{id} - Clicking outside or pressing Escape dismisses the dropdown
- Combines with existing full search results — suggestions are fast previews, not the main result list
3. Mobile-Responsive Enhancements
- Filters panel is collapsed by default on mobile, toggleable via a "Filters" button
- Touch targets minimum 44px (WCAG 2.1)
- Results grid switches to single column below 600px viewport width
- Search input and filters panel stack vertically on small screens
- Add CSS breakpoints via inline styles and a
useMediaQueryhook - Bottom navigation-style action buttons on mobile (Add Book, Bookmarks, Settings become icon-only)
Component Hierarchy
LibraryPage
├── Header (title, count, action buttons)
├── SearchInput
│ ├── TextInput (debounced 300ms)
│ ├── VoiceSearchButton (microphone icon)
│ └── SearchSuggestions (dropdown, debounced 200ms)
├── FiltersButton (mobile: toggle; desktop: always visible)
├── FiltersPanel (collapsible on mobile)
│ ├── GenreSelect
│ ├── AuthorSelect
│ ├── StatusSelect
│ └── ClearFiltersButton
├── LoadingState (skeleton grid)
├── ErrorState (message + retry button)
├── EmptyState (no results / no books)
└── ResultsGrid (responsive: auto-fill vs single column)
Mobile-First CSS Strategy
- Use inline styles with
@mediaqueries in a sharedbreakpoints.tsutility - Breakpoints: sm = 480px, md = 768px, lg = 1024px
- Base styles are mobile-first (single column, full width)
- Media queries expand to multi-column grid and horizontal layout on larger screens