Add mobile-responsive design with full feature parity: - Bottom sheet (vaul) with 3 snap points for map+list coexistence - Swipeable property cards with horizontal scroll-snap - Hamburger menu with health, tasks, user info - Full-screen map with repositioned legend (top-left on mobile) - Filter FAB opening Sheet drawer - TaskProgressDrawer from bottom on mobile - All changes gated behind useIsMobile() hook (768px breakpoint) - Desktop layout completely untouched New components: MobileBottomSheet, SwipeableCardRow, PropertyCardCompact, MobileMenu Also fixes: idempotent longitude migration, React hooks order
4.4 KiB
4.4 KiB
Mobile Responsive Design
Goal
Make the realestate-crawler frontend fully responsive with complete feature parity on mobile devices. All desktop functionality must be preserved, adapted to mobile-friendly interaction patterns.
Current State
The frontend (React 19, TypeScript, Vite, Tailwind CSS, Radix UI, Mapbox GL) has partial mobile support:
useIsMobile()hook with 768px breakpoint- Filter panel converts to FAB + Sheet on mobile
- Scattered
md:hidden/hidden md:blockpatterns
Missing: bottom sheet for map+list coexistence, swipeable property cards, compact header, touch-optimized interactions, mobile task progress.
Design Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Map + list coexistence | Bottom sheet over full-screen map | Natural pattern for geo apps (Google Maps, Zillow) |
| Property browsing | Horizontal swipeable cards | Quick scanning with map context preserved |
| Heavy features (filters, POI, tasks) | Sheet drawers | Already partly implemented; consistent UX |
| Bottom sheet library | vaul |
Lightweight (~4KB), snap points, gesture handling, Radix-compatible |
| Card swiping | CSS scroll-snap | Native, no extra dependency, smooth performance |
| Desktop impact | None | All changes gated behind useIsMobile() |
Layout Architecture
Mobile (< 768px)
+----------------------------+
| HEADER (compact, h-12) |
| Logo | hamburger |
+----------------------------+
| |
| |
| FULL-SCREEN MAP |
| |
| |
| |
+----------------------------+ <- draggable handle
| Bottom Sheet |
| Stats bar (compact) |
| +----+ +----+ +----+ | <- swipeable cards
| |Card|>|Card|>|Card| |
| +----+ +----+ +----+ |
| |
| (drag up to expand to |
| full list view) |
+----------------------------+
FAB buttons (bottom-right, above sheet):
Filter icon - opens filter Sheet
POI icon - opens POI manager Sheet
Bottom Sheet Snap Points
80px- collapsed: drag handle + listing count35%- peek (default): stats + swipeable property cards85%- expanded: full scrollable list with sort controls
Desktop (>= 768px)
No changes. Existing layout preserved exactly.
Component Changes
New Components
| Component | Purpose |
|---|---|
MobileBottomSheet |
vaul-based drawer with 3 snap points, contains stats + cards + list |
SwipeableCardRow |
Horizontal scroll-snap container of compact property cards, syncs with map |
PropertyCardCompact |
~280px wide card for swipe browsing (thumbnail, price, beds, sqm) |
MobileMenu |
Hamburger menu Sheet with health, tasks, user info |
Modified Components
| Component | Changes |
|---|---|
App.tsx |
Conditional layout: mobile renders full-screen map + MobileBottomSheet + FABs |
Header.tsx |
Hamburger menu on mobile, hide inline items |
StatsBar.tsx |
Render inside bottom sheet header on mobile |
Map.tsx |
Full-screen on mobile, legend to top-left, bidirectional sync with cards |
ListView.tsx |
Render inside expanded bottom sheet on mobile |
TaskProgressDrawer.tsx |
Bottom Sheet on mobile instead of right-side drawer |
FilterPanel.tsx |
Touch-friendly sizing, no structural changes |
POIManager.tsx |
Touch-friendly sizing when in Sheet |
Unchanged
- Backend, API, services, auth
- Core logic, data flow, state management
- Desktop layout
Map-Card Synchronization
- Swipe to a card -> map pans/highlights that listing's marker
- Tap a map marker -> cards scroll to that listing
- Maintains spatial context during browsing
Navigation & Touch
- Header: logo + hamburger on mobile. Hamburger opens Sheet with health, tasks, user info
- Two FABs stacked bottom-right (filter, POI). Auto-hide when sheet is fully expanded
- All tap targets minimum 44x44px
- No hover-dependent interactions on mobile (tooltips become tap-to-show)
- Map popup close buttons enlarged
- Gesture isolation: horizontal card swipe, vertical sheet drag, and map pan don't conflict
New Dependencies
vaul(~4KB gzipped) - bottom sheet drawer with snap points and gestures
Scope Boundaries
- No new backend work
- No new API endpoints
- No changes to authentication flow
- No changes to data models
- Purely frontend layout and interaction changes