Skip to content

feat(frontend): Premium barcode scanner UX — haptic feedback, scan preview, batch mode, timeout handling #784

@ericsocrat

Description

@ericsocrat

Problem Statement

The barcode scanner is the app's primary entry point for in-store users, yet the current UX has several friction points that slow down the scan → decision flow:

  1. Torch toggle too small — hard to tap in a dimly-lit store aisle, doesn't meet 44×44px WCAG target
  2. No scan feedback — users don't know if the camera is actively scanning or frozen
  3. No timeout indicator — if a barcode isn't recognized after 10+ seconds, users don't know what to do
  4. Manual EAN input field cramped on mobile — the fallback for when scanning fails
  5. Camera permission recovery — if denied once, users get stuck (fixed partially in PR fix(frontend): scanner — add camera permission recovery and scan feedback (#702) #745, but needs verification)
  6. No haptic feedback — modern food scanning apps (Yuka, CodeCheck) provide a satisfying vibration on successful scan
  7. Scan result transition — after successful scan, the transition to product detail is abrupt
  8. Scan history — exists but is not prominently accessible during the scanning flow
  9. No "batch scan" mode — users scanning a full grocery cart want to scan multiple products in sequence

Design Vision — Premium Scanner UX

Active Scanning State

┌─────────────────────────────────┐
│  ← Scanner                  🔦  │  Large torch toggle (48px)
│                                  │
│  ╔═══════════════════════════╗   │
│  ║                           ║   │
│  ║     [Camera Viewfinder]   ║   │
│  ║                           ║   │
│  ║   ┌───────────────────┐   ║   │
│  ║   │    ▮▮▮▮ ▮▮▮▮      │   ║   │  Animated scan line
│  ║   └───────────────────┘   ║   │
│  ║                           ║   │
│  ╚═══════════════════════════╝   │
│                                  │
│  🟢 Scanning... point at barcode │  Status indicator
│                                  │
│  ┌──────────────────────────┐   │
│  │ 📝 Enter EAN manually    │   │  Full-width manual input
│  └──────────────────────────┘   │
│                                  │
│  📋 Recent scans (3)         ▸   │  Quick access to history
└─────────────────────────────────┘

Successful Scan Transition

┌─────────────────────────────────┐
│                                  │
│  ╔═══════════════════════════╗   │
│  ║   ✅ Product Found!       ║   │  Green overlay
│  ║                           ║   │
│  ║   Piątnica Skyr           ║   │  Product name preview
│  ║   🟢 95 — Excellent       ║   │  Score preview
│  ║                           ║   │
│  ║   [View Details →]        ║   │  Tap to navigate
│  ║   [Scan Another]          ║   │  Stay in scanner
│  ╚═══════════════════════════╝   │
│                                  │
│  📱 Haptic buzz on scan          │  Device vibration
└─────────────────────────────────┘

Product Not Found

┌─────────────────────────────────┐
│                                  │
│  ╔═══════════════════════════╗   │
│  ║   ❌ Product Not Found    ║   │  Clear feedback
│  ║                           ║   │
│  ║   EAN: 5900512345678      ║   │  Show scanned code
│  ║                           ║   │
│  ║   [Submit This Product]   ║   │  Community contribution
│  ║   [Try Again]             ║   │  Quick retry
│  ╚═══════════════════════════╝   │
│                                  │
└─────────────────────────────────┘

Implementation Plan

Phase 1 — Scanner UX Polish

  • Enlarge torch toggle to 48×48px minimum
  • Add animated scan line in viewfinder
  • Add scanning status indicator ("Scanning...", "Processing...", "Camera starting...")
  • Add timeout after 15 seconds: "Having trouble? Try manual entry or adjust lighting"

Phase 2 — Scan Feedback

  • Haptic vibration on successful scan (navigator.vibrate(200))
  • Success overlay with product preview (name, score, image)
  • "Scan Another" vs "View Details" choice
  • Sound option (optional, off by default)

Phase 3 — Manual Input Enhancement

  • Full-width EAN input field
  • Auto-format as user types (add spaces for readability)
  • EAN checksum validation in real-time (is_valid_ean() client-side)
  • "Paste from clipboard" button

Phase 4 — Batch Scanning Mode

  • Toggle "Batch mode" — scans auto-add to a temporary list
  • Review all scanned products at once
  • One-tap "Compare all" or "Add to list"
  • Counter badge showing scan count

Test Requirements

Vitest Tests

  • Scanner status states: idle, scanning, found, not-found, error, timeout
  • Haptic vibration called on scan success
  • EAN input validation (checksum, format, paste)
  • Timeout triggers after configurable delay
  • Batch mode: products accumulate correctly

Playwright E2E

  • Scanner page loads at 320px viewport
  • Manual EAN input submits and navigates to product
  • Camera permission error shows recovery instructions
  • History section accessible

Accessibility

  • Torch toggle ≥48×48px with aria-label
  • Status messages announced by screen reader
  • Camera fallback (manual input) always accessible

Verification Checklist

  • cd frontend && npx tsc --noEmit — 0 errors
  • cd frontend && npx vitest run — all tests pass
  • Manual test on real device — haptic works, camera permissions handled
  • 320px viewport — all elements visible, no overflow
  • CHANGELOG.md updated under [Unreleased]

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium: normal priorityenhancementNew feature or requestfrontendFrontend / Next.js / ReactmobilescanneruxUser experience improvement

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions