Files
familysync/.planning/milestones/v1.1-phases/17-ui-optimization-polish/17-03-SUMMARY.md
T
2026-06-18 22:21:38 -04:00

128 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: "17"
plan: "03"
subsystem: pwa/layout
tags: [layout-fix, fab-overlap, bottom-tab-bar, phone-only, regression-guard, css-tokens, d-01, d-02]
dependency_graph:
requires:
- apps/pwa/src/styles/tokens.css — --bottom-chrome-h token (provided by plan 17-01)
provides:
- FAB overlap fix: CalendarShell.tsx FAB bottom = calc(var(--bottom-chrome-h) + var(--space-6))
- Phone content padding: App.tsx contentStyle paddingBottom = var(--bottom-chrome-h) (phone-only)
- Regression guard: apps/pwa/e2e/layout.spec.ts — D-01 overlap assertion (iphone + pixel)
affects:
- apps/pwa/src/components/CalendarShell.tsx (FAB bottom offset)
- apps/pwa/src/App.tsx (contentStyle paddingBottom)
- apps/pwa/e2e/layout.spec.ts (new overlap assertion)
tech_stack:
added: []
patterns:
- "CSS calc() combining --bottom-chrome-h token with --space-6 for FAB clearance above BottomTabBar"
- "Spread pattern ...(phone ? { paddingBottom: var(--bottom-chrome-h) } : {}) for phone-only contentStyle"
- "Playwright boundingBox() geometry assertion: fabBox.y + fabBox.height <= navBox.y"
key_files:
created: []
modified:
- apps/pwa/src/components/CalendarShell.tsx
- apps/pwa/src/App.tsx
- apps/pwa/e2e/layout.spec.ts
decisions:
- "FAB bottom uses calc(var(--bottom-chrome-h) + var(--space-6)) — positions FAB 24px above bar top edge regardless of safe-area-inset value"
- "contentStyle paddingBottom is phone-only via spread pattern — desktop has no BottomTabBar and must not gain extra bottom padding (RESEARCH Pitfall 2)"
- "Overlap assertion skips desktop profile — the desktop New Event button is a toolbar button, not the FAB; geometry check is semantically wrong for sidebar layout"
- "Full e2e suite run on all three profiles confirmed zero regressions from layout changes"
metrics:
duration: "~18 minutes"
completed_date: "2026-06-18"
tasks_completed: 3
tasks_total: 3
files_changed: 3
status: complete
---
# Phase 17 Plan 03: Phone Layout Overlap Fix — Summary
Fixed the long-standing phone (≤767px) fixed-chrome overlap where the `position: fixed` BottomTabBar was covering the New Event FAB and occluding the bottom color-legend chips, using the `--bottom-chrome-h` token from plan 17-01. Added a permanent D-01 overlap regression assertion to `layout.spec.ts`. Full 3-profile Playwright suite is green.
## What Was Built
**One-liner:** FAB lifted above BottomTabBar via `calc(var(--bottom-chrome-h) + var(--space-6))`, phone content reserves `--bottom-chrome-h` padding, permanent overlap regression guard added to CI.
### Task 1: FAB lift + phone content padding (CalendarShell.tsx, App.tsx)
**CalendarShell.tsx** (phone-only FAB, lines 463491):
- Changed `bottom: 'var(--space-6)'``bottom: 'calc(var(--bottom-chrome-h) + var(--space-6))'`
- FAB now sits 24px (var(--space-6)) above the BottomTabBar top edge regardless of safe-area-inset
- All other FAB style properties unchanged (right, width, height, zIndex, etc.)
**App.tsx** (contentStyle, lines 155164):
- Added phone-only spread: `...(phone ? { paddingBottom: 'var(--bottom-chrome-h)' } : {})`
- Phone content area now reserves space equal to the BottomTabBar height
- Desktop branch has no paddingBottom — geometry unchanged
- Build: `pnpm --filter @familysync/pwa build` exits 0
### Task 2: FAB↔BottomTabBar overlap regression assertion (layout.spec.ts)
Added new `test.describe` block "D-01 regression guard — FAB does not overlap BottomTabBar":
- Test name: "New Event FAB does not overlap BottomTabBar (A — phone only)"
- Skips on desktop (`testInfo.project.name === 'desktop'`)
- Locates FAB via `page.getByRole('button', { name: 'New Event' })` and bar via `page.getByRole('navigation', { name: 'Main navigation' })`
- Asserts `fabBox.y + fabBox.height <= navBox.y` (FAB bottom ≤ BottomTabBar top)
- Passes GREEN on iphone (390×844 WebKit) and pixel (412×915 Chromium)
### Task 3: Small-viewport sweep across all three profiles
- `pnpm --filter @familysync/pwa test:e2e` (all 3 profiles): **115 passed, 23 skipped, 0 failed**
- iphone profile: all layout.spec.ts assertions pass including new D-01 guard
- pixel profile: all layout.spec.ts assertions pass including new D-01 guard
- desktop profile: all layout.spec.ts assertions pass; D-01 guard correctly skipped
- No violations flagged by Rules 14 assertions
- Admin tab tap target still meets ≥44px after layout changes
- Color-legend chips confirmed fully visible via playwright-cli screenshot at 390×844
## Visual Confirmation (playwright-cli @390×844)
Screenshot taken via playwright-cli (Chromium, viewport 390×844, reloaded to pick up phone layout):
- **New Event FAB (+)**: clearly positioned above the BottomTabBar with visible gap
- **Color-legend chips** ("Dev User" blue, "Family" pink): fully visible between calendar content and BottomTabBar — not clipped or occluded
- **BottomTabBar** (Calendar, Lists, Admin): fully visible at the bottom edge
## Verification Results
| Check | Result |
|-------|--------|
| `grep 'calc(var(--bottom-chrome-h) + var(--space-6))'` in CalendarShell.tsx | PASS |
| `grep "paddingBottom: 'var(--bottom-chrome-h)'"` in App.tsx | PASS |
| `grep 'New Event FAB does not overlap BottomTabBar'` in layout.spec.ts | PASS |
| `pnpm --filter @familysync/pwa build` | PASS |
| Playwright iphone + pixel layout.spec.ts (overlap assertion) | PASS — 32 passed, 2 skipped |
| Full 3-profile `pnpm --filter @familysync/pwa test:e2e` | PASS — 115 passed, 23 skipped, 0 failed |
| playwright-cli visual confirmation @390×844 | PASS — FAB above bar, legend chips visible |
| Desktop geometry unchanged | PASS — no desktop layout changes |
## Deviations from Plan
None. Plan executed exactly as written. The three-task sequence (CSS fix, regression guard, sweep) was completed without any deviations. The FAB bottom value, phone contentStyle spread pattern, and overlap assertion all match the plan specification exactly.
## Known Stubs
None. All changes are wired and fully functional.
## Threat Flags
None. CSS-only layout offsets plus a Playwright geometry test — no new network endpoints, auth paths, or data flows introduced.
## Self-Check: PASSED
| Item | Result |
|------|--------|
| CalendarShell.tsx exists | FOUND |
| App.tsx exists | FOUND |
| layout.spec.ts exists | FOUND |
| SUMMARY.md exists | FOUND |
| Commit 5e1c714 (Task 1) | FOUND |
| Commit 85a803f (Task 2) | FOUND |
| CalendarShell FAB bottom grep | PASS |
| App.tsx paddingBottom grep | PASS |
| layout.spec.ts overlap assertion grep | PASS |