Archived
feat: mobile book search and discovery with voice search, suggestions, and responsive layout
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# 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 search
|
||||
- `GET /api/books/{id}/` — book detail
|
||||
- `GET /api/books/genres/` — genre discovery
|
||||
- `GET /api/books/authors/` — author discovery
|
||||
- Frontend `LibraryPage` and `BookDetailPage` components exist but lacked API client methods and types (fixed in this PR).
|
||||
|
||||
## Frontend API Client Additions
|
||||
|
||||
### `frontend/src/types/book.ts` — New exports
|
||||
|
||||
```typescript
|
||||
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**: `useVoiceSearch` in `frontend/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: `SearchSuggestions` rendered as a dropdown below the search input
|
||||
- On each keystroke (debounced 200ms), fetches `GET /api/books/?q=...&page_size=5` for 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 `useMediaQuery` hook
|
||||
- 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 `@media` queries in a shared `breakpoints.ts` utility
|
||||
- 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
|
||||
Reference in New Issue
Block a user