wrongmove/docs/plans/2026-02-21-mobile-responsive-design.md
Viktor Barzin a744b33578
feat: make frontend fully responsive with mobile-first layout
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
2026-02-21 11:34:53 +00:00

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:block patterns

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 count
  • 35% - peek (default): stats + swipeable property cards
  • 85% - 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