docs(phase-27): complete phase execution

This commit is contained in:
2026-04-10 23:52:28 +02:00
parent 2b27309b23
commit acb4672aed
2 changed files with 185 additions and 3 deletions

View File

@@ -4,7 +4,7 @@ milestone: v2.1
milestone_name: Public Discovery
status: verifying
stopped_at: Completed 27-03-PLAN.md
last_updated: "2026-04-10T21:48:34.545Z"
last_updated: "2026-04-10T21:52:24.791Z"
last_activity: 2026-04-10
progress:
total_phases: 14
@@ -25,8 +25,8 @@ See: .planning/PROJECT.md (updated 2026-04-09)
## Current Position
Phase: 27 (top-nav-restructure-and-search-bar-rethink) — EXECUTING
Plan: 4 of 4
Phase: 999.1
Plan: Not started
Status: Phase complete — ready for verification
Last activity: 2026-04-10

View File

@@ -0,0 +1,182 @@
---
phase: 27-top-nav-restructure-and-search-bar-rethink
verified: 2026-04-10T00:00:00Z
status: passed
score: 5/5 must-haves verified
re_verification: false
human_verification:
- test: "Visual verification of TopNav on desktop"
expected: "Logo, Home/Collection/Setups links, search bar, and user avatar visible in a horizontal bar at the top"
why_human: "CSS layout and visual rendering cannot be verified programmatically"
- test: "AuthPromptModal triggered by anonymous Collection/Setups click"
expected: "Clicking Collection or Setups while not logged in opens AuthPromptModal — no navigation occurs"
why_human: "E2E seed runs as authenticated user; unauthenticated state requires a separate fixture"
- test: "BottomTabBar visible on mobile viewport"
expected: "4-tab bar fixed at screen bottom on 375px viewport; TopNav shows only logo and avatar (no nav links)"
why_human: "Responsive CSS breakpoints require a real browser to validate"
- test: "FAB not visible on mobile"
expected: "Floating action button is hidden below md breakpoint"
why_human: "CSS hidden/block toggle requires visual inspection"
- test: "CatalogSearchOverlay triggered from TopNav search bar and BottomTabBar Search tab"
expected: "Clicking search bar (desktop) or Search tab (mobile) opens the full-screen overlay"
why_human: "Overlay interaction requires a live browser session"
---
# Phase 27: Top Nav Restructure & Search Bar Rethink — Verification Report
**Phase Goal:** Replace the minimal TotalsBar with a persistent top navigation bar (logo, section links, catalog search, user avatar) and move mobile navigation to a bottom tab bar — elevating Setups to top-level and removing the landing page hero
**Verified:** 2026-04-10
**Status:** passed
**Re-verification:** No — initial verification
---
## Goal Achievement
### Observable Truths (from ROADMAP Success Criteria)
| # | Truth | Status | Evidence |
|---|-------|--------|---------|
| 1 | A persistent top nav bar shows logo, Home/Collection/Setups links, catalog search, and user avatar on desktop | ✓ VERIFIED | `TopNav.tsx` renders logo (`LucideIcon name="package"` + "GearBox"), `<nav class="hidden md:flex">` with Home/Collection/Setups `NavLinkOrButton` elements, a `hidden md:flex` search button calling `openCatalogSearch`, and `<UserMenu />` or "Sign in" |
| 2 | Clicking Collection or Setups while anonymous triggers AuthPromptModal instead of navigating | ✓ VERIFIED | `NavLinkOrButton` renders `<button onClick={openAuthPrompt}>` when `isProtected && !isAuthenticated`; same pattern in `BottomTabBar.tsx` |
| 3 | On mobile, navigation appears as a fixed bottom tab bar with Home, Collection, Setups, and Search icons | ✓ VERIFIED | `BottomTabBar.tsx` uses `fixed bottom-0 left-0 right-0 md:hidden` with 4 tabs (Home/house, Collection/package, Setups/layers, Search/search); framer-motion entry animation included |
| 4 | The landing page no longer has a hero section — content starts with Popular Setups | ✓ VERIFIED | `src/client/routes/index.tsx` contains no `HeroSection`, no "Discover Gear", no `lucide-react` import, no `useAuth`, no `useUIStore`; `LandingPage` renders `<PopularSetupsSection />` as first child |
| 5 | Setups has its own top-level route accessible from the nav bar, not nested in Collection tabs | ✓ VERIFIED | `src/client/routes/setups/index.tsx` exists with `createFileRoute("/setups/")` rendering `<SetupsView />`; `collection/index.tsx` has `TAB_ORDER = ["gear", "planning"]` with no "setups" reference |
**Score: 5/5 truths verified**
---
### Required Artifacts
| Artifact | Expected | Status | Details |
|----------|----------|--------|---------|
| `src/client/components/TopNav.tsx` | Persistent top navigation bar replacing TotalsBar | ✓ VERIFIED | 130 lines, exports `TopNav`, uses `useMatchRoute`, `openAuthPrompt`, `openCatalogSearch`, `hidden md:flex`, `<UserMenu />` |
| `src/client/components/BottomTabBar.tsx` | Mobile bottom tab bar with 4 navigation items | ✓ VERIFIED | 95 lines, exports `BottomTabBar`, uses `fixed bottom-0 md:hidden z-20`, framer-motion, `openCatalogSearch`, `openAuthPrompt` |
| `src/client/routes/setups/index.tsx` | Top-level Setups route page | ✓ VERIFIED | Exists, `createFileRoute("/setups/")`, renders `<SetupsView />` in `max-w-7xl` container |
| `src/client/routes/collection/index.tsx` | Collection page with Gear and Planning tabs only | ✓ VERIFIED | `TAB_ORDER = ["gear", "planning"]`, `z.enum(["gear", "planning"]).catch("gear")`, zero "setups" occurrences |
| `src/client/routes/__root.tsx` | Root layout with TopNav, BottomTabBar, and updated FAB visibility | ✓ VERIFIED | Imports and renders `<TopNav />` and `<BottomTabBar />`; no `TotalsBar`; FAB wrapped in `<div class="hidden md:block">`; root div has `pb-16 md:pb-0` |
| `src/client/routes/index.tsx` | Landing page without hero section | ✓ VERIFIED | Starts with `<PopularSetupsSection />`; no hero, no unused imports |
| `e2e/dashboard.spec.ts` | Updated dashboard E2E tests matching new nav layout | ✓ VERIFIED | Tests for TopNav presence, nav links, bottom tab bar on mobile; old hero tests replaced |
| `e2e/collection.spec.ts` | Updated collection E2E tests without Setups tab assertions | ✓ VERIFIED | "setups tab URL falls back to gear tab" replaces old setups-tab test; `/setups` route test added |
---
### Key Link Verification
| From | To | Via | Status | Details |
|------|----|-----|--------|---------|
| `__root.tsx` | `TopNav.tsx` | `import { TopNav }` + `<TopNav />` | ✓ WIRED | Line 22 import, line 138 render |
| `__root.tsx` | `BottomTabBar.tsx` | `import { BottomTabBar }` + `<BottomTabBar />` | ✓ WIRED | Line 19 import, line 177 render |
| `TopNav.tsx` | `uiStore.ts` | `useUIStore``openCatalogSearch`, `openAuthPrompt` | ✓ WIRED | Both actions destructured and called |
| `BottomTabBar.tsx` | `uiStore.ts` | `useUIStore``openCatalogSearch`, `openAuthPrompt` | ✓ WIRED | Both actions destructured and called |
| `setups/index.tsx` | `SetupsView.tsx` | `import { SetupsView }` + `<SetupsView />` | ✓ WIRED | Direct import and render in `SetupsPage` |
---
### Data-Flow Trace (Level 4)
| Artifact | Data Variable | Source | Produces Real Data | Status |
|----------|--------------|--------|-------------------|--------|
| `src/client/routes/index.tsx``PopularSetupsSection` | `data` from `useDiscoverySetups(6)` | `useDiscovery.ts` hook → `/api/discovery/setups` | Yes — real DB query through existing discovery hooks | ✓ FLOWING |
| `src/client/routes/index.tsx``RecentItemsSection` | `data` from `useDiscoveryItems(8)` | `useDiscovery.ts` hook → `/api/discovery/items` | Yes | ✓ FLOWING |
| `src/client/routes/index.tsx``TrendingCategoriesSection` | `data` from `useDiscoveryCategories(12)` | `useDiscovery.ts` hook → `/api/discovery/categories` | Yes | ✓ FLOWING |
| `TopNav.tsx` | `auth?.user` from `useAuth()` | `useAuth` hook → `/api/auth/me` | Yes | ✓ FLOWING |
| `BottomTabBar.tsx` | `auth?.user` from `useAuth()` | `useAuth` hook → `/api/auth/me` | Yes | ✓ FLOWING |
---
### Behavioral Spot-Checks
| Behavior | Check | Result | Status |
|----------|-------|--------|--------|
| `TopNav.tsx` exports `TopNav` function | `grep -c "export function TopNav"` | 1 | ✓ PASS |
| `BottomTabBar.tsx` exports `BottomTabBar` function | `grep -c "export function BottomTabBar"` | 1 | ✓ PASS |
| `__root.tsx` has no TotalsBar reference | `grep -c "TotalsBar"` | 0 | ✓ PASS |
| `collection/index.tsx` has no "setups" string | `grep -c "setups"` | 0 | ✓ PASS |
| `__root.tsx` includes `/setups` in isPublicRoute | `grep '/setups"'` | line 123 present | ✓ PASS |
| `__root.tsx` has mobile bottom padding | `grep 'pb-16 md:pb-0'` | line 137 present | ✓ PASS |
| `layers` icon in iconData curated set | `grep '"layers"'` | line 209 present | ✓ PASS |
| `house` icon resolves in lucide-react | `node -e "... icons['House']"` | true | ✓ PASS |
---
### Requirements Coverage
The plans declare NAV-01 through NAV-05 as requirement IDs. These identifiers do NOT exist in `.planning/REQUIREMENTS.md` — the requirements file covers v2.1 milestones (PUBL-xx, DISC-xx, CATL-xx, SEED-xx, INFR-xx) and does not include a NAV-xx section. Phase 27 was planned after the requirements document was last updated (2026-04-09).
| Requirement | Source Plan(s) | Description (from ROADMAP/context) | Status |
|-------------|---------------|------------------------------------|--------|
| NAV-01 | 27-00, 27-01, 27-03 | Persistent top nav bar with logo, section links, search, avatar | ✓ SATISFIED — TopNav implemented, wired in __root.tsx |
| NAV-02 | 27-01, 27-03 | Auth interception: anonymous clicks on protected nav links open AuthPromptModal | ✓ SATISFIED — NavLinkOrButton and BottomTabBar both implement this |
| NAV-03 | 27-01, 27-03 | Active route highlighted in nav | ✓ SATISFIED — useMatchRoute drives active/inactive class in both components |
| NAV-04 | 27-00, 27-03 | Landing page hero removed; content starts with Popular Setups | ✓ SATISFIED — index.tsx confirmed clean |
| NAV-05 | 27-00, 27-02 | Setups elevated to top-level /setups route; removed from Collection tabs | ✓ SATISFIED — setups/index.tsx exists; collection/index.tsx clean |
**Note:** NAV-01 through NAV-05 are phase-internal requirement identifiers not registered in REQUIREMENTS.md. They are not orphaned — they were defined for this phase only and carry no cross-phase traceability obligation. No formal update to REQUIREMENTS.md is required unless the project owner chooses to retroactively add the NAV section.
---
### Anti-Patterns Found
| File | Pattern | Severity | Impact |
|------|---------|----------|--------|
| `BottomTabBar.tsx` line 52 | Uses icon name `"house"` for Home tab; plan specified `"home"` and neither is in the curated `iconGroups` list | Info | No user impact — `LucideIcon` resolves icon names directly from `lucide-react`'s `icons` object, and `House` exists in the package. Renders correctly. The curated set is only used by the IconPicker UI, not LucideIcon rendering. |
No blocker or warning anti-patterns found.
---
### Human Verification Required
#### 1. TopNav Visual Layout (Desktop)
**Test:** Open http://localhost:5173 in a wide browser window (1280px+)
**Expected:** Top bar shows: package icon + "GearBox" text on left, "Home / Collection / Setups" links in center (hidden on narrow), search button on right, user avatar or "Sign in" link
**Why human:** CSS `hidden md:flex` visibility and flex layout require a real browser
#### 2. AuthPromptModal on Anonymous Clicks
**Test:** Open the app while logged out, click "Collection" or "Setups" in the nav
**Expected:** AuthPromptModal appears — no navigation to /collection or /setups
**Why human:** E2E seed environment is authenticated; unauthenticated test fixture is not in scope
#### 3. Mobile Bottom Tab Bar
**Test:** Use DevTools to set viewport to 375px width, reload
**Expected:** Bottom bar with 4 icon+label items (Home, Collection, Setups, Search) is fixed at the bottom; TopNav shows only logo and avatar
**Why human:** Responsive CSS requires a live browser viewport
#### 4. FAB Hidden on Mobile
**Test:** In 375px viewport, verify no floating action button appears
**Expected:** FAB is not visible on mobile; visible on desktop (1280px+)
**Why human:** `hidden md:block` wrapper CSS requires visual inspection
#### 5. Search Overlay Triggers
**Test:** Click the search bar in TopNav (desktop) and the Search tab in BottomTabBar (mobile)
**Expected:** CatalogSearchOverlay opens in both cases
**Why human:** UI interaction and overlay rendering require a live browser
---
### Gaps Summary
No gaps found. All 5 phase success criteria are met by the implementation:
- `TopNav.tsx` is a complete, fully-wired component with auth interception, active-route detection, search trigger, and user menu
- `BottomTabBar.tsx` is a complete mobile nav with framer-motion animation, auth interception, and search trigger
- `/setups` route exists and renders `SetupsView` in a standard page layout
- `collection/index.tsx` has exactly 2 tabs (Gear, Planning) with no Setups reference
- `__root.tsx` mounts both new components, removes TotalsBar, hides FAB on mobile, adds public route for /setups, and adds mobile bottom padding
- `index.tsx` (landing page) is clean of hero section, unused imports, and starts with Popular Setups
- E2E test files are updated with post-Phase-27 assertions
Five human verification items remain for visual and interaction confirmation but do not represent code gaps.
---
_Verified: 2026-04-10_
_Verifier: Claude (gsd-verifier)_