From 08467494bf497aca098112fc51c3104954700c1d Mon Sep 17 00:00:00 2001 From: lorentz Date: Sun, 3 May 2026 16:05:11 -0400 Subject: [PATCH] docs(02-01): complete plan 02-01 shell components summary - HeaderBar, BottomNav, MoreDrawer, analyzer placeholder created - TypeScript and Next.js build both pass (273 routes) - Requirements SHELL-02..04, SHELL-06, NAV-01..03, DRAWER-01..05 addressed --- .../02-01-SUMMARY.md | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 .planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md diff --git a/.planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md b/.planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md new file mode 100644 index 0000000..eaed23b --- /dev/null +++ b/.planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md @@ -0,0 +1,129 @@ +--- +phase: 02-mobile-shell-more-drawer +plan: 01 +subsystem: mobile-shell +tags: [mobile, navigation, shell, drawer, components] +dependency_graph: + requires: [] + provides: + - components/mobile/HeaderBar.tsx + - components/mobile/BottomNav.tsx + - components/mobile/MoreDrawer.tsx + - app/mobile/analyzer/page.tsx + affects: + - app/mobile/layout.tsx (Plan 02 will wire these in) +tech_stack: + added: [] + patterns: + - shadcn Sheet (side="right") for drawer + - Controlled open/onOpenChange props for shared drawer state + - pathname.startsWith(href) for active tab detection + - initials-circle pattern from UserMenu (no shadcn avatar primitive) + - pt-safe / pb-safe from Phase 1 brand.css utilities +key_files: + created: + - components/mobile/HeaderBar.tsx + - components/mobile/BottomNav.tsx + - components/mobile/MoreDrawer.tsx + - app/mobile/analyzer/page.tsx + modified: [] +decisions: + - Sheet side="right" (locked per DRAWER-02 in CONTEXT.md) + - No shadcn avatar primitive — initials-circle pattern matches existing UserMenu + - Bell onClick intentionally empty (SHELL-03 placeholder, Phase 7+ wires real notifications) + - No page title in HeaderBar — pages render their own H1 + - analyzer/page.tsx is a deliberate "coming soon" placeholder — Phase 6 owns the real feed +metrics: + duration_minutes: 5 + completed_date: "2026-05-03" + tasks_completed: 5 + tasks_total: 5 + files_created: 4 + files_modified: 0 +--- + +# Phase 02 Plan 01: Mobile Shell Components Summary + +Three new reusable shell components and an analyzer route placeholder — the building blocks Plan 02 will wire into `app/mobile/layout.tsx` to complete the mobile shell redesign. + +## What Was Built + +**MoreDrawer** (`components/mobile/MoreDrawer.tsx`) — shadcn Sheet (side="right") with controlled `open`/`onOpenChange` props so both the header avatar and the bottom-nav More button share one drawer instance. Three sections: +- Mobile sections: Engagement (in-shell, no ExternalLink) +- Full site: Quotes, Configuration Items, Backup Status, Ticket Digest, Admin/Sync (each with ExternalLink icon) +- Account: user initials + name/email (read-only) + Sign out (calls `signOut()` then navigates to `/auth/sign-in`) + +**HeaderBar** (`components/mobile/HeaderBar.tsx`) — sticky header with `bg-background/95 backdrop-blur border-b pt-safe`. Left: WulfMark + "Pulse" wordmark linked to `/mobile/dashboard`. Right: Bell placeholder (`aria-label="Notifications"`, empty onClick) + compact avatar circle (h-7 w-7) calling `onAvatarClick` prop. No page title in the header. + +**BottomNav** (`components/mobile/BottomNav.tsx`) — fixed bottom bar (`border-t bg-background pb-safe`, `max-w-lg mx-auto`, `h-16`). Four tabs: Dashboard (LayoutDashboard), Tickets (Ticket), Finance (DollarSign), Analyzer (Sparkles) — all with `pathname.startsWith(href)` active detection (text-primary when active, text-muted-foreground otherwise). Fifth cell: More button calling `onMoreClick` prop. + +**Analyzer placeholder** (`app/mobile/analyzer/page.tsx`) — minimal server component with "coming soon" card. Resolves the `/mobile/analyzer` route so the new Analyzer tab doesn't 404 before Phase 6 (ANL-01..06) ships the real feed. + +## Requirements Addressed + +| Requirement | Status | +|-------------|--------| +| SHELL-02 | Sticky header, brand mark+wordmark, /mobile/dashboard link, backdrop blur, border-b | +| SHELL-03 | Bell placeholder with aria-label, empty onClick | +| SHELL-04 | Avatar circle h-7 w-7, triggers drawer via onAvatarClick | +| SHELL-06 | Fixed bottom nav, max-w-lg mx-auto, border-t, pb-safe | +| NAV-01 | 4 tab icons: LayoutDashboard, Ticket, DollarSign, Sparkles + Menu for More | +| NAV-02 | 4 routes: /mobile/dashboard, /mobile/tickets, /mobile/finance, /mobile/analyzer | +| NAV-03 | pathname.startsWith(href) active detection, text-primary/text-muted-foreground | +| DRAWER-01 | More button in BottomNav triggers shared drawer via onMoreClick prop | +| DRAWER-02 | Sheet side="right" (locked decision) | +| DRAWER-03 | Mobile sections: Engagement /mobile/engagement (no ExternalLink) | +| DRAWER-04 | Full site: Quotes, Config Items, Backup Status, Ticket Digest, Admin/Sync with ExternalLink | +| DRAWER-05 | Account: user display (read-only) + Sign out via signOut() + router.push('/auth/sign-in') | + +## Locked Decisions Honored + +- `side="right"` — locked in CONTEXT.md DRAWER-02 +- No shadcn `avatar` primitive — uses existing initials-circle pattern from UserMenu +- Bell `onClick` is empty — SHELL-03 explicitly says "placeholder only this iteration" +- No `

` in HeaderBar — SHELL-02 explicit: "pages render their own H1" +- MoreDrawer uses controlled state (props, not internal) — both triggers share one drawer + +## Notes for Plan 02 + +Plan 02 rewrites `app/mobile/layout.tsx` and deletes `app/mobile/nav/page.tsx`. When wiring the new components: + +```tsx +// In layout.tsx (Plan 02): +const [drawerOpen, setDrawerOpen] = useState(false); + + setDrawerOpen(true)} /> + + setDrawerOpen(true)} /> +``` + +## Deviations from Plan + +None — plan executed exactly as written. + +## Known Stubs + +| File | Stub | Reason | +|------|------|--------| +| `app/mobile/analyzer/page.tsx` | "coming soon" card, no data | Intentional — Phase 6 (ANL-01..06) owns the real mobile analyzer feed. This file exists only to prevent a 404 on the new BottomNav Analyzer tab. | +| `components/mobile/HeaderBar.tsx` | Bell onClick is empty | Intentional — SHELL-03 explicitly defers real notifications to Phase 7+. | + +## Threat Flags + +None — no new network endpoints, no new auth paths, no new DB access. All trust boundaries match the plan's threat model exactly. + +## Self-Check: PASSED + +Files verified: +- `components/mobile/HeaderBar.tsx` — exists +- `components/mobile/BottomNav.tsx` — exists +- `components/mobile/MoreDrawer.tsx` — exists +- `app/mobile/analyzer/page.tsx` — exists + +Commits verified: +- `6630589` — feat(02-01): create MoreDrawer component +- `14375f1` — feat(02-01): create HeaderBar component +- `a42c0a8` — feat(02-01): create BottomNav component +- `3fc0ee3` — feat(02-01): add /mobile/analyzer placeholder + +Build: `npx tsc --noEmit --pretty` exits 0, `npm run build` exits 0 (273 routes generated, `/mobile/analyzer` in route table).