Approach C: Map-First with Modern Chrome - Horizontal filter bar replacing sidebar - React Router for URL state / deep linking - Redesigned property cards with better visual hierarchy - Refined color palette and typography - Tabbed listing detail sheet
6.3 KiB
UI/UX Redesign: Map-First with Modern Chrome
Date: 2026-02-28 Status: Approved Approach: C — Preserve map-first architecture, modernize filter UX, visual polish, URL state
Context
The realestate-crawler frontend is a React 19 + Vite + Tailwind 4 + shadcn/ui SPA with Mapbox GL hexgrid heatmap, Tinder-style swipe review, POI travel times, and real-time WebSocket task progress. Competitive analysis of Rightmove, Zoopla, and ImmobilienScout24 identified best practices to adopt while preserving our unique differentiators.
Pain Points Addressed
- Visual polish — Functional but plain shadcn defaults; needs better typography, spacing, card design
- Filter workflow — Sidebar with collapsible accordions is hard to discover and use
- Navigation & URL state — No deep linking, browser back/forward doesn't work, can't share filtered views
- Property cards — Need richer info display, better image presentation, clearer hierarchy
Design Decisions
1. Layout & Navigation Architecture
Desktop (>= 768px):
+------------------------------------------------------------------+
| Header (h-12): [Logo] [Rent|Buy] [Health] --- [Tasks] [User] |
+------------------------------------------------------------------+
| Filter Bar (h-10): [Price ▾] [Beds ▾] [Size ▾] [More ▾] | chips |
+------------------------------------------------------------------+
| Main Content Area |
| Map (default) | Split (map 60% + list 40%) | List | Saved |
+------------------------------------------------------------------+
| Status Bar (h-8): [1,234 results] [Avg: £2,100] [Map|Split|List] |
+------------------------------------------------------------------+
Key changes:
- Sidebar removed entirely — filter bar is horizontal, below header
- Rent/Buy toggle promoted into header
- Active filter chips inline in filter bar
- View mode toggle in status bar
- Full viewport width for map (no sidebar stealing space)
Mobile (< 768px):
+------------------------------------------+
| Header (h-12): [Logo] ---- [Filter] [≡] |
+------------------------------------------+
| Full-screen Map + FABs |
+------------------------------------------+
| Bottom Sheet (draggable) |
| Active filter chips (scrollable row) |
| [Stats] [Horizontal card row] |
+------------------------------------------+
Mobile filter opens as full-screen modal (not sidebar sheet).
React Router URL structure:
/ → Map view, default filters
/map?type=rent&minPrice=1000&maxPrice=2500&beds=2
/split?type=buy&district=hackney
/list?type=rent&sort=price_asc
/saved
/listing/12345678 → Deep link to listing detail
2. Filter System
Horizontal filter bar replaces the sidebar:
- Primary filters always visible as compact dropdowns: Listing type, Price range, Bedrooms, Min size
- "More filters" button opens a popover panel with: Max size, Price/m², Furnishing, District, Available from, Last seen days, POI travel time filters
- Active filter chips render in a second row when filters are applied (removable with ×)
- "Show Listings" / "Scrape New" buttons right-aligned in filter bar
- "Color by" visualization control moves to status bar
Mobile: Full-screen filter modal with stacked fields and sticky "Apply" button.
3. Property Cards
Full card (list/split view):
+---------------------------------------+
| [Image Carousel - 16:10 ratio] |
| 1/9 [♥] [↗ RM] |
+---------------------------------------+
| £2,500/mo ● Good Deal |
| 2 bed · 65 m² · £38/m² |
| Shoreditch, London E1 |
+---------------------------------------+
| 🚶 12min 🚲 8min 🚌 25min |
| Foxtons · Listed 3d ago |
+---------------------------------------+
Key improvements:
- Larger image carousel (16:10 aspect ratio)
- Price as dominant element — large, bold
- Deal indicator with colored dot + text
- Key metrics on one line: beds · sqm · price/sqm
- POI travel times as compact badges
- Agency + freshness de-emphasized at bottom
- Heart + external link overlaid on image
Compact card (mobile bottom sheet):
+------------------+
| [Photo 4:3] |
| £2,500 2bd |
| Shoreditch |
+------------------+
4. Visual Design System
Color palette:
| Role | Value | Usage |
|---|---|---|
| Primary | Slate 900 #0f172a |
Headers, primary text |
| Accent | Teal 600 #0d9488 |
CTAs, active filters, map |
| Good deal | Emerald 500 #10b981 |
Price indicators |
| Above avg | Amber 500 #f59e0b |
Warning indicators |
| Background | White / Slate 50 | Card surfaces |
| Muted | Slate 100-200 | Filter bar bg |
| Map dark | Slate 800 | Map overlay controls |
Typography:
- Price:
text-xl font-bold tracking-tight - Location:
text-sm font-medium - Metrics:
text-sm text-muted-foreground - Chips/badges:
text-xs font-medium
Spacing: 4px base, 16px card padding, 12px card gaps, 8px inline gaps.
5. Listing Detail Sheet
Larger drawer (60% viewport desktop, 90% mobile) with tabbed sections:
- Photo gallery — Full width, swipeable, with photo/floorplan toggle
- Header — Price, deal indicator, key metrics, actions
- Tabs: Overview (features + description), Travel (POI distances), Price History (timeline), Details (property attributes)
What's Preserved (No Changes)
- Hexgrid heatmap visualization (Web Worker)
- Tinder-style swipe review mode
- POI travel time calculations
- WebSocket real-time task progress
- Streaming NDJSON data loading
- Dual auth (Passkey + SSO)
- Mobile bottom sheet with snap points
- SwipeableCardRow horizontal scroll
Technical Approach
- Add
react-router-domfor URL-based navigation - Decompose App.tsx (713 lines) — extract filter state to context provider
- Extract duplicated utilities (formatDuration, formatCurrency, etc.)
- New component:
FilterBar(replacesFilterPanelsidebar layout) - Refactor
PropertyCardfor new visual hierarchy - Update
index.csswith new color palette CSS variables - Add error boundaries
Out of Scope
- Backend API changes (all data already available)
- New features (saved searches, alerts, text search)
- State management library (keep React state, just decompose)