Files
simandClaude Sonnet 5.5 a2e4321ac7
Build and Push Lunchtime Images (Kaniko) / build-and-push (push) Successful in 1m44s
Rework My Orders stats and add responsive UI checks
My Orders: year calendar and lunch profile first, chips and "How you
compare" removed, open and paid payments merged into one table (open
first, then newest). Activity is now a line chart with a cumulative
switch and finer buckets (daily up to ~3 months, weekly up to ~13).
Cards get subtle elevation and tighter spacing.

Responsive: phone tab strip instead of the side menu, heatmap fits
narrow screens, grouped column-chart labels are truncated, the manager
weekday table scrolls instead of overflowing.

Tooling: viewports.mjs (presets, overflow detector), shoot.mjs --sizes
and --select, tests/responsive.ui.spec.ts, docs/ui-testing.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 23:15:25 +00:00

4.4 KiB

UI checks: does it look right on phones and desktops?

Tools live in src/e2e/. They need the dev stack (src/dev/devenv.sh start, app on :8020).

Tool What it is for
viewports.mjs Shared presets (iphone-se 375x667, android-small 360x740, iphone-14 390x844, pixel-7 412x915, ipad 768x1024, laptop 1280x800, desktop 1440x900, fhd 1920x1080), groups and findHorizontalOverflow(page)
shoot.mjs Screenshots in any viewport, reports console errors, failed requests and horizontal overflow (exit code 1)
tests/responsive.ui.spec.ts Regression test: no page overflows its viewport (home, create, three stats pages, order, order admin)

The process after any layout change

  1. Typecheck: cd src/frontend && npx tsc --noEmit.
  2. Automatic overflow check, all sizes, for the pages you touched (needs a user with data, --as=admin has the most):
    cd src/e2e
    node shoot.mjs /stats/orderee /stats/manager /stats/admin --as=admin --sizes=all           # light
    node shoot.mjs /stats/orderee /stats/manager /stats/admin --as=admin --sizes=all --dark    # dark
    
    Any WARN OVERFLOW <size> <path>: ... offenders line is a bug: the page scrolls sideways on that device. The offenders are the elements that stick out. Fix: wrap tables in scroll={{ x: true }}, give flex children minWidth: 0, use minmax(min(Npx, 100%), 1fr) in grids.
  3. Look at it. Overflow is only one kind of bug. Shoot the extremes and read the PNGs:
    node shoot.mjs /stats/orderee --as=admin --sizes=iphone-se,android-small,fhd --full
    
    • Smallest phone (360 / 375): truncated or overlapping labels, tall single-column stacks, controls wrapping ("Stat us"), things that need sideways scrolling without a hint.
    • Tablet (768): where the layout switches; the awkward in-between.
    • Widest desktop (1920): content stays centred and readable, nothing stretched.
    • Dark mode on at least one phone and one desktop size.
  4. Zoom on a single widget instead of reading a 14000px full-page shot:
    node shoot.mjs /stats/manager --as=admin --sizes=android-small,desktop --select='.ant-card:has-text("Participants per order")'
    
  5. Run the regression spec (check = iphone-se, pixel-7, ipad, desktop; RESPONSIVE_SIZES=all for all eight):
    npx playwright test --project=ui responsive
    RESPONSIVE_SIZES=all npx playwright test --project=ui responsive
    
    Many parallel page loads can be slow on the Vite dev server; if you see timeouts add --workers=2.

Getting data worth looking at

A fresh user has no data and shows only the empty state. Options:

  • --as=admin in the dev stack usually has history. --seed or {order} / {admin} in the path create an order with two submissions.
  • The API can only create things "now". For charts over time, backdate rows directly in src/backend/data/burger_orders.db (submissions.created_at, accepted, paid). Remember the original values and restore them afterwards.

Gotchas

  • --sizes takes preset names, groups (phones, tablets, desktops, check, all) or WxH. A name is never both a group and a preset.
  • --mobile still means the Pixel 7 preset; --sizes supersedes it.
  • findHorizontalOverflow ignores elements inside an intentional scroller (overflow-x: auto|scroll|hidden|clip) and fixed overlays, so heatmaps that scroll on purpose are not reported. That also means a clipped-but-unhinted scroller is not caught: look at the screenshots.
  • A pre-existing React warning (useForm not connected to a Form) appears once per page load in every shoot; it is not caused by the stats pages.
  • In this repo's shell, grep is a wrapper that honours .gitignore-style ignore files and silently skips some source files (for example lib/stats.ts). Use command grep when a search result looks suspiciously empty.

Conventions the stats pages follow (so they pass)

  • Cards come from ChartCard; grids from CardGrid (minmax(min(Npx, 100%), 1fr)).
  • Wide content scrolls inside its own container (tables: scroll={{ x: true }}; the year calendar opens scrolled to the latest week) or shrinks to fit (the weekday x hour heatmap).
  • Column-chart labels are truncated per group of slots (labelEvery); the full text is in the tooltip.
  • Phones (<= 640px) get a tab strip (Segmented) instead of the side menu in StatisticsView.tsx.