Session 37: Design system Phase F — mobile parity: 5-tab bar, More sheet, PWA polish (1872 tests)

VYNDR 2.0 conversion, Phase F (mobile is the PWA we launch first). Frontend-only;
zero backend changes.

- BottomTabBar rewritten to the §6 5-tab spec: Slate/Terminal/Scan/Ledger/More,
  with Scan as the prominent raised grade-green action. Shown for anon too (only
  mobile nav). Integrated More bottom sheet (sheet-up, backdrop dismiss, 48px mono
  rows). iOS safe-area + 44px touch targets.
- Nav hamburger retired on mobile (tab bar owns nav).
- globals.css mobile section: tab-bar hidden >=768, main bottom padding,
  grade-hero 80px, terminal-grid stacks, game-lines horizontal scroll.
- PWA: manifest shortcuts (Slate/Scan/Terminal) + categories; viewport-fit=cover.

Gotcha: `as const` on the TABS array broke type-check (distinct literal types);
fixed with a shared TabDef interface.

19 new tests. Backend 1853 -> 1872, 145 suites, zero regressions. Web build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kev
2026-06-16 10:11:52 -04:00
parent 612f5e0b72
commit f88961885c
10 changed files with 433 additions and 141 deletions
+70 -2
View File
@@ -4,8 +4,76 @@
2026-06-16
## Current Phase
SHIP BUILD v36.0 — VYNDR 2.0 design system, Phase E: remaining screens
dashboard Bloomberg lines, compare/invite/help/about, login/pricing (Session 36)
SHIP BUILD v37.0 — VYNDR 2.0 design system, Phase F: mobile parity
5-tab bar, More sheet, mobile CSS, PWA manifest/viewport (Session 37)
## Session 37 (2026-06-16) — SHIPPED
Phase F: mobile parity — the mobile build is the PWA we launch first. Converted
the bottom nav to the §6 5-tab spec, added the More bottom sheet, mobile CSS,
and PWA polish. Frontend-only; ZERO backend changes. Backend 1853 → **1872
tests** (+19), 145 suites, zero regressions. Web build clean (exit 0).
### F.2/F.3 — Bottom tab bar + More sheet (`components/BottomTabBar.tsx` rewritten)
- 5 tabs per §6: **Slate · Terminal · Scan · Ledger · More**. **Scan is the
prominent raised action** — a 46px grade-green circle lifted above the bar
(it's the core action). Active = `--g-a`, inactive = `--text-2`, 9px mono
labels, 64px bar, `env(safe-area-inset-bottom)`, ≥44px touch targets.
- **More** opens an integrated bottom sheet: `fade-in` backdrop (dismiss on tap)
+ `sheet-up` scanlines panel, handle pill, MORE title + × close, 10 secondary
routes (Compare/Tracker/Report/Invite/Pricing/Account/Settings/Help/About/
Responsible) as 48px mono rows. Dismisses on item nav / backdrop / ×.
- BEHAVIOR CHANGE: the bar now shows for ANON users too (previously hidden when
signed-out). Slate/Terminal/Scan are open routes and this is the only mobile
nav; gated taps (Ledger/Account) bounce through the Session-34 AuthGate. Still
hidden on auth flows + landing (`HIDE_ON`). Dropped the old Parlay tab (the
global ParlayTray keeps its own trigger).
### F.4 — Mobile header
- Retired the Nav hamburger on mobile (`display:none`) — the tab bar + More sheet
own mobile nav now. The Nav already hid desktop links <768px, so the mobile
header is just wordmark + bell + read-meter + avatar. Mobile panel is now dead
code (harmless).
### F.5 — Mobile CSS (`globals.css`)
- `.mobile-tab-bar` hidden ≥768px; `main` bottom-padded `calc(84px + safe-area)`
<768px so content clears the bar; `.grade-hero` → 80px <640px (GradeResultCard
letter tagged `grade-hero`); `.terminal-grid` stacks to 1fr ≤768px (Terminal
grid tagged); `.game-lines-grid` horizontal-scroll + sticky `.team-col` <640px.
### F.6 — PWA polish
- `manifest.json`: added **shortcuts** (Slate/Scan/Terminal deep-links), categories
`["sports","finance","productivity"]`. Already standalone + theme/bg `#06060B`.
- `layout.tsx` viewport: added `viewportFit: 'cover'` (notch/home-indicator) so
the tab bar's safe-area padding has room. apple-mobile-web-app-* already set
via metadata.appleWebApp (Session 27).
### Files created
- `tests/unit/vyndrMobile.test.js` (19 tests: 5 tabs, prominent Scan, safe area,
More sheet items/backdrop/44px, mobile CSS rules, Nav hamburger hidden,
grade-hero hook, manifest standalone/shortcuts/categories, viewport-fit)
### Files modified
- `web/src/components/BottomTabBar.tsx` (full rewrite), `web/src/components/Nav.tsx`
(hamburger hidden), `web/src/app/globals.css` (mobile section),
`web/src/components/vyndr/GradeResultCard.tsx` (grade-hero class),
`web/src/app/terminal/page.tsx` (terminal-grid class),
`web/public/manifest.json` (shortcuts/categories), `web/src/app/layout.tsx`
(viewportFit)
### Gotcha logged
- `as const` on the TABS array made each entry a distinct literal type, so
`isSheet`/`primary`/`href` failed type-check on tabs lacking them. Fixed with a
shared `TabDef` interface. (The build worker exits code 1 on type errors; a
piped `| tail` masked it — always check the build exit code, not just the tail.)
### Deferred (Sessions 38+)
- Living-layer ticker/heartbeat data, i18n, a11y toggle wiring, SW, paywall,
parlay math = Phase G (Session 38). §13 QA = Session 39.
---
## Session 36 (2026-06-16) — SHIPPED
## Session 36 (2026-06-16) — SHIPPED