Files
familysync/.planning/phases/17-ui-optimization-polish/17-CONTEXT.md
T

129 lines
14 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: UI Optimization & Polish - Context
**Gathered:** 2026-06-17
**Status:** Ready for planning
<domain>
## Phase Boundary
A **visual-identity & polish pass** for the PWA, spanning four bounded workstreams (AC from this discussion; D added from Phase 19 UAT, see Decisions §D):
- **A — Phone-layout polish.** Fix the long-standing phone (≤767px) fixed-chrome overlap where the `position: fixed` BottomTabBar covers the New Event FAB (FAB lands on the Admin tab) and occludes the bottom of the calendar + the colour-legend chips, then sweep other small-viewport spacing / tap-target / overflow issues. CSS/layout only, no behaviour change.
- **B — Branding assets.** Generate a real **FamilySync** logo and drop it into the already-built `BrandSlot` seam (`apps/pwa/src/components/BrandSlot.tsx`), and produce a **complete favicon / PWA-icon set** to replace the placeholder stubs in `apps/pwa/public/` (`icon-192.png` 699 B, `icon-512.png`, `apple-touch-icon.png` 617 B — all generated stubs; there is currently **no `favicon.ico`/`favicon.svg`** and index.html links only the apple-touch icon).
- **C — Theme-token groundwork.** Restructure `apps/pwa/src/styles/tokens.css` from its single light `:root` into a **themeable semantic-token layer** (swappable by `data-theme` / `prefers-color-scheme`). Light stays the only *shipped* theme — this is enabling groundwork only.
- **D — UAT-surfaced UI fixes** (from Phase 19 live UAT). Wire a **logout control** to the existing `fetchLocalLogout()` (no backend), add **success feedback** to admin create/reset-password flows, fix **dialog/popup bottom-center positioning**, and **rework the clunky admin navigation**. See Decisions §D (D-07…D-10).
**Out of scope (explicitly deferred this discussion, 2026-06-17):**
- **Shipped dark theme + light/dark/system toggle** → backlog **999.20** (Phase 17's token groundwork is the enabling seam).
- **Broader "modern styling" visual refresh** (contemporary restyle of login/calendar/event-form/lists/admin) → backlog **999.21**, flagged for a **future milestone** — a redesign track, not a polish phase.
This stays a focused polish + branding + groundwork pass, **not a redesign**.
</domain>
<decisions>
## Implementation Decisions
### A — Phone-layout polish
- **D-01:** Fix the seed defect (BottomTabBar overlapping the FAB + colour legend) AND run a bounded small-viewport sweep — the Phase 7 `layout.spec.ts` assertions (tap targets ≥44px, no horizontal overflow, critical elements in-viewport, accessible names) are the checklist; fix what they flag across phone routes. Bounded and checklist-driven, not a free-form audit.
- **D-02:** **Fix technique and regression-guard mechanism are the researcher's call** (deferred from discussion). Inputs the researcher must weigh: the ROADMAP/todo fix sketch (lift FAB to `bottom: calc(56px + env(safe-area-inset-bottom,0px) + var(--space-6))` + matching content `padding-bottom`, OR shrink the `100dvh` column by the bar height) vs. a single shared `--bottom-chrome-h` token consumed by both the FAB offset and the content padding (single source of truth). Researcher also decides whether to add a permanent overlap assertion to `layout.spec.ts` (FAB/legend must not intersect the BottomTabBar rect on phone profiles) vs. playwright-cli manual verification only. **Default lean if evidence is neutral:** shared token + add the CI assertion (hardest to regress), but this is the researcher's decision to make on the merits.
### B — Branding assets
- **D-03:** **Logo + full icon set are AI-generated in-phase** (option 2a). Claude generates the logo and the complete icon/favicon set from the brief below, wires them in (BrandSlot `<img>`, `apps/pwa/public/` files, `index.html` `<link>`s, and the `vite-plugin-pwa` manifest `icons[]` in `apps/pwa/vite.config.ts`), and the user approves the result before it's final. No external designer / user-supplied art.
- **D-04:** Deliver a **complete** icon set, not just a logo: `favicon.ico` + `favicon.svg`, `icon-192.png`, `icon-512.png`, a **proper maskable** 512 (the current manifest reuses the non-maskable 512 as maskable — a real maskable needs safe-zone padding), and `apple-touch-icon.png` (180×180). Update `index.html` (add the missing `<link rel="icon">`s; `theme-color` currently `#4A90D9`) and the `vite.config.ts` manifest to reference them.
- **D-05:** Drive the logo through the existing `BrandSlot` seam contract — swap the placeholder `<div>` for an `<img>` and override the `--brand-logo-*` tokens — **without changing `LoginPage` layout** (the seam was built in Phase 19 precisely to isolate this). Keep the accessibility shape: `<h1>` carries the app name, logo image is decorative (`alt=""` / `aria-hidden`), no layout shift.
### C — Theme-token groundwork
- **D-06:** Restructure `tokens.css` into a themeable layer (semantic tokens resolvable per theme via `data-theme`/`prefers-color-scheme`) — **groundwork only** (option 3a). **Do NOT** author dark palette values, wire `prefers-color-scheme` to actually flip, or add a toggle this phase. Light remains the sole shipped theme. Keep the existing invariant: no hard-coded hex/px in component files — all values stay in `tokens.css`. The restructure must leave the Schedule-X `--sx-color-*` overrides (bottom of tokens.css) working unchanged.
### D — UAT-surfaced UI findings (from Phase 19 live UAT, 2026-06-17)
Surfaced by the operator during the Phase 19 local-auth UAT and **routed here by operator decision** — these are UI concerns, not Phase 19 auth blockers. Phase 19 ships functionally complete; Phase 17 owns the UI. (Recorded in `.planning/phases/19-local-auth-no-oidc-mode/19-UAT.md` as F-01…F-04.)
- **D-07 (F-02) — Wire a logout control into the UI.** Logout is fully plumbed but unreachable: the endpoint `POST/GET /api/auth/local/logout` works (200, clears cookie — BL-02 verified live) and `fetchLocalLogout()` exists at `apps/pwa/src/api/client.ts:127`, but **no component calls it** (zero logout buttons in `apps/pwa/src`). Add a logout control (likely in `SettingsSheet.tsx` and/or `AppNav`) that calls the existing client function + redirects to `/login`. **No backend work** — UI wiring only. (Slightly beyond pure "polish" — it's a small new control; planner should size it.)
- **D-08 (F-01) — Add success feedback to admin local-account actions.** Admin create-member and reset-password both succeed (verified at DB/login level in UAT) but show **no success toast/confirmation**, leaving the operator unsure it worked. Add success feedback to those admin flows (`AdminPage.tsx`).
- **D-09 (F-03) — Fix dialog/popup positioning.** Popups/sheets render **bottom-center instead of properly centered**. Fits the fixed-chrome/sheet-positioning sweep already in workstream A; likely the same dialog/sheet CSS (`SettingsSheet.tsx` and shared dialog styles). Verify across phone + desktop via playwright-cli.
- **D-10 (F-04) — Rework the clunky admin navigation.** Admin UI navigation reads as clunky and needs a rework. Larger UX item than the others — planner should decide whether it fits this phase's "polish" budget or warrants its own slice. (`AdminPage.tsx`, admin nav/tab surface.)
### Claude's Discretion
- **D-02** (fix technique + regression guard) is explicitly delegated to the researcher/planner.
- Exact small-viewport issues surfaced by the `layout.spec` sweep (D-01) — fix as found, within the no-behaviour-change boundary.
- Logo visual execution within the brand brief (see Specific Ideas) — subject to user approval at the checkpoint.
### Folded Todos
- **`2026-06-13-pwa-phone-bottombar-overlap.md`** (`area: pwa-ui`, `resolves_phase: 17`) — the phase's seed defect. Phone-layout fixed BottomTabBar overlaps the New Event FAB + colour legend at ≤767px. Reproduced 2026-06-13 via playwright-cli at 390×844 (FAB over Admin tab; "Dev User" legend clipped) vs 1280×800 (no overlap). Long-standing (BottomTabBar dates to Phase 04), not a Phase 10 regression. This is workstream A's anchor — its `files:` list (`App.tsx`, `BottomTabBar.tsx`, `CalendarShell.tsx`) is the fix surface.
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Phase scope & seed defect
- `.planning/ROADMAP.md` §"Phase 17: UI Optimization & Polish" — goal, three-workstream scope, scope boundary, seed-defect detail + CSS fix sketch.
- `.planning/todos/pending/2026-06-13-pwa-phone-bottombar-overlap.md` — the folded seed-defect todo (repro, fix sketch, affected files).
- `.planning/ROADMAP.md` §"Phase 999.20" / §"Phase 999.21" — the deferred dark-mode and styling-refresh backlog items (what is explicitly NOT in this phase).
### A — Phone layout (fix surface)
- `apps/pwa/src/App.tsx``window.matchMedia('(max-width: 767px)')` phone breakpoint + `contentStyle` (currently reserves no `padding-bottom` for the fixed bar).
- `apps/pwa/src/components/BottomTabBar.tsx``position: fixed; height: calc(56px + env(safe-area-inset-bottom)); z-index: 200`.
- `apps/pwa/src/components/CalendarShell.tsx` — the "New Event" FAB (`position: fixed; bottom: var(--space-6); right: var(--space-6)`).
- `apps/pwa/e2e/layout.spec.ts` — Phase 7 quality-bar assertions (UI-SPEC Rules 14: ≥44px tap targets, no overflow, in-viewport, accessible names); the sweep checklist AND the home for any new overlap regression assertion.
- `apps/pwa/playwright.config.ts``iphone` (iPhone 14/WebKit 390×844), `pixel` (Pixel 7/Chromium 412×915), `desktop` (Desktop Chrome 1280×720) profiles to verify across.
### B — Branding
- `apps/pwa/src/components/BrandSlot.tsx` — the Phase-17 branding seam; header documents the `--brand-logo-*` token contract and the swap-div-for-`<img>` plan.
- `.planning/phases/19-local-auth-no-oidc-mode/19-UI-SPEC.md` §Brand Slot — the seam's design contract (referenced by BrandSlot.tsx).
- `apps/pwa/public/``apple-touch-icon.png`, `icon-192.png`, `icon-512.png` (placeholder stubs to replace).
- `apps/pwa/index.html` — current `<link rel="apple-touch-icon">` + `theme-color` meta (no `<link rel="icon">` yet).
- `apps/pwa/vite.config.ts` §`VitePWA({ manifest: { icons: [...] } })` (lines ~2941) — PWA manifest icon list to update (incl. the improper maskable reuse).
### C — Theming
- `apps/pwa/src/styles/tokens.css` — the single light `:root` token system to restructure into a themeable layer (note the Schedule-X `--sx-color-*` overrides at the bottom and the `--brand-logo-*` defaults).
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- **`BrandSlot` seam** (`apps/pwa/src/components/BrandSlot.tsx`): purpose-built in Phase 19 to absorb the real logo with zero `LoginPage` layout change — swap the placeholder div for an `<img>` and set `--brand-logo-*`. The branding workstream is wiring, not new architecture.
- **`layout.spec.ts` + 3 Playwright profiles** (Phase 7/14): a ready, CI-wired structural quality bar (tap targets / overflow / in-viewport / a11y names) — doubles as the sweep checklist (D-01) and the natural home for a regression guard (D-02).
- **CSS custom-property token system** (`tokens.css`): everything is already a variable with "no hard-coded hex/px in components" enforced — the themeable-layer restructure (D-06) builds on an already-favourable structure rather than fighting inline values.
- **`vite-plugin-pwa` manifest** (`vite.config.ts`): the icon set is declared in one place; replacing stubs = update files in `public/` + the manifest `icons[]` + `index.html` links.
### Established Patterns
- **Phone/desktop split at 767/768px** via `matchMedia` in `App.tsx`; phone uses top AppNav (PhoneNav `<header>`) + fixed BottomTabBar (sole `<nav aria-label="Main navigation">`), desktop uses a sidebar with no bottom bar. Fixes must be phone-scoped and not touch desktop geometry.
- **Safe-area awareness:** BottomTabBar already uses `env(safe-area-inset-bottom)`; any FAB-lift / content-padding fix must compose with the same inset (notched-device correctness).
- **Accessibility invariants** the layout fix must preserve: single nav landmark on mobile, ≥44px tap targets, no horizontal overflow (the very assertions in `layout.spec.ts`).
### Integration Points
- FAB offset (`CalendarShell.tsx`) ↔ bar height (`BottomTabBar.tsx`) ↔ content padding (`App.tsx`) — D-02's "shared `--bottom-chrome-h` token" option would make these three agree via one source of truth.
- Logo image ↔ `--brand-logo-*` tokens (`tokens.css`) ↔ `BrandSlot``LoginPage`.
- Icon files (`public/`) ↔ `index.html` links ↔ `vite.config.ts` PWA manifest — all three must reference the same regenerated asset set.
</code_context>
<specifics>
## Specific Ideas
**Logo / brand brief (user, 2026-06-17):**
- **FamilySync *is* the brand** — family-oriented, the name is the identity.
- **Caricature-family vibes** — a warm, characterful family feel (not a cold/corporate geometric mark).
- **Warm tones.**
- **Rounded corners / rounded shapes.**
- Overall it should **"make you feel comfortable and at home."**
This brief drives the AI-generated logo + icon set (D-03/D-04). Present generated options at a user-approval checkpoint before finalizing; the warm/rounded/at-home direction is the acceptance lens. Note the current `theme-color` is `#4A90D9` (cool blue) and `--color-shared-family` is rose `#f25c7a` — the warm-tone brief may motivate revisiting the brand/theme accent during the token-groundwork work (keep within light-theme scope).
</specifics>
<deferred>
## Deferred Ideas
- **Shipped dark theme + light/dark/system toggle** — captured as backlog **999.20** (PWA dark mode / theming). Phase 17 ships the enabling token groundwork only.
- **Modern visual styling refresh** (contemporary restyle across high-visibility surfaces) — captured as backlog **999.21**, flagged for a **future milestone** (redesign risk; own track).
### Reviewed Todos (not folded)
- **`2026-06-10-gitea-ci-regression-and-docker-publish.md`** — surfaced as a weak keyword match (score 0.6) but is CI/tooling work already shipped in Phase 8/14; unrelated to this UI phase. Not folded.
</deferred>
---
*Phase: 17-ui-optimization-polish*
*Context gathered: 2026-06-17*