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
This commit is contained in:
parent
29ff7fd8fd
commit
08467494bf
1 changed files with 129 additions and 0 deletions
129
.planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md
Normal file
129
.planning/phases/02-mobile-shell-more-drawer/02-01-SUMMARY.md
Normal file
|
|
@ -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 `<h1>` 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);
|
||||
|
||||
<HeaderBar onAvatarClick={() => setDrawerOpen(true)} />
|
||||
<MoreDrawer open={drawerOpen} onOpenChange={setDrawerOpen} />
|
||||
<BottomNav onMoreClick={() => 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).
|
||||
Loading…
Add table
Add a link
Reference in a new issue