---
phase: 27-top-nav-restructure-and-search-bar-rethink
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/client/components/TopNav.tsx
- src/client/components/BottomTabBar.tsx
autonomous: true
requirements:
- NAV-01
- NAV-02
- NAV-03
must_haves:
truths:
- "TopNav renders logo, Home/Collection/Setups links, search bar, and user avatar on desktop"
- "Clicking Collection or Setups while anonymous calls openAuthPrompt instead of navigating"
- "Active section is visually highlighted in the nav"
- "BottomTabBar renders 4 tabs (Home, Collection, Setups, Search) with Lucide icons on mobile"
- "Tapping Search tab calls openCatalogSearch"
artifacts:
- path: "src/client/components/TopNav.tsx"
provides: "Persistent top navigation bar replacing TotalsBar"
exports: ["TopNav"]
- path: "src/client/components/BottomTabBar.tsx"
provides: "Mobile bottom tab bar with 4 navigation items"
exports: ["BottomTabBar"]
key_links:
- from: "src/client/components/TopNav.tsx"
to: "src/client/stores/uiStore.ts"
via: "openCatalogSearch, openAuthPrompt"
pattern: "useUIStore.*openCatalogSearch|useUIStore.*openAuthPrompt"
- from: "src/client/components/BottomTabBar.tsx"
to: "src/client/stores/uiStore.ts"
via: "openCatalogSearch, openAuthPrompt"
pattern: "useUIStore.*openCatalogSearch|useUIStore.*openAuthPrompt"
---
Create the two new navigation components: TopNav (desktop persistent nav bar) and BottomTabBar (mobile fixed bottom tab bar).
Purpose: These components are the core UI deliverables of Phase 27, replacing the minimal TotalsBar with full navigation. They implement D-01 through D-03 (top nav structure), D-07 (nav search bar), D-12 through D-14 (mobile bottom tab bar), and D-17 (search trigger from nav).
Output: Two new component files ready to be wired into __root.tsx in Plan 03.
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/27-top-nav-restructure-and-search-bar-rethink/27-CONTEXT.md
@.planning/phases/27-top-nav-restructure-and-search-bar-rethink/27-RESEARCH.md
From src/client/stores/uiStore.ts:
```typescript
openCatalogSearch: (mode: "collection" | "thread") => void;
closeCatalogSearch: () => void;
openAuthPrompt: () => void;
closeAuthPrompt: () => void;
```
From src/client/hooks/useAuth.ts:
```typescript
// Returns { data: { user: User | null }, isLoading: boolean }
export function useAuth(): UseQueryResult<{ user: User | null }>;
```
From src/client/lib/iconData.tsx:
```typescript
// Renders a Lucide icon by name string. Available icons include: package, home, layers, search
export function LucideIcon({ name, size, className }: { name: string; size?: number; className?: string }): JSX.Element;
```
From src/client/components/UserMenu.tsx:
```typescript
export function UserMenu(): JSX.Element;
```
From src/client/components/TotalsBar.tsx (pattern reference — being replaced):
```typescript
// Sticky positioning pattern: "sticky top-0 z-10 bg-white border-b border-gray-100"
// Container: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"
// Height: "h-14"
```
Task 1: Create TopNav componentsrc/client/components/TopNav.tsx
src/client/components/TotalsBar.tsx
src/client/stores/uiStore.ts
src/client/components/UserMenu.tsx
src/client/hooks/useAuth.ts
Create `src/client/components/TopNav.tsx` that replaces TotalsBar with a full navigation bar.
**Structure (per D-01):**
- Sticky top bar: `sticky top-0 z-10 bg-white border-b border-gray-100` (same as TotalsBar)
- Container: `mx-auto max-w-7xl px-4 sm:px-6 lg:px-8`, flex row, `h-14`
- Left: Logo — `` with `` and "GearBox" text. Same styling as TotalsBar logo.
- Center: Desktop nav links (hidden on mobile with `hidden md:flex`) — Home, Collection, Setups
- Right: Search bar (desktop only) + UserMenu or "Sign in" link
**Active route detection (per D-03):**
```typescript
const matchRoute = useMatchRoute();
const isHome = !!matchRoute({ to: "/" });
const isCollection = !!matchRoute({ to: "/collection", fuzzy: true });
const isSetups = !!matchRoute({ to: "/setups", fuzzy: true });
```
Active link gets `text-gray-900`, inactive gets `text-gray-500 hover:text-gray-700`.
**Auth-gated nav links (per D-02):**
Create a `NavLinkOrButton` internal component. When `isAuthenticated` is false and the link is protected (Collection, Setups), render a `cd /home/jean-luc-makiola/Development/projects/GearBox && grep -c "export function TopNav" src/client/components/TopNav.tsx && grep -c "useMatchRoute" src/client/components/TopNav.tsx && grep -c "openAuthPrompt" src/client/components/TopNav.tsx && grep -c "openCatalogSearch" src/client/components/TopNav.tsx
- src/client/components/TopNav.tsx exists and exports `export function TopNav()`
- File imports `useMatchRoute` from `@tanstack/react-router`
- File contains `openAuthPrompt` call for anonymous nav interception
- File contains `openCatalogSearch("collection")` for search bar click
- File contains `hidden md:flex` for desktop-only nav links
- File contains `` for authenticated users
- File contains `
TopNav component renders logo, nav links (Home/Collection/Setups), search bar, and user section. Anonymous clicks on Collection/Setups fire AuthPromptModal. Active route is highlighted. Desktop nav links hidden on mobile.Task 2: Create BottomTabBar componentsrc/client/components/BottomTabBar.tsx
src/client/components/FabMenu.tsx
src/client/stores/uiStore.ts
src/client/hooks/useAuth.ts
src/client/lib/iconData.tsx
Create `src/client/components/BottomTabBar.tsx` for mobile navigation.
**Structure (per D-13):**
- Fixed bottom: `fixed bottom-0 left-0 right-0 md:hidden z-20 bg-white border-t border-gray-100`
- z-20 so CatalogSearchOverlay (which uses higher z-index) renders above it
- 4 tab items in a flex row with `justify-around`
- Each tab: icon (LucideIcon, size 20) + label (text-xs) stacked vertically
**Tab items (per D-13, D-14):**
1. Home — icon: `home`, label: "Home", always ``
2. Collection — icon: `package`, label: "Collection", `` if authenticated, `cd /home/jean-luc-makiola/Development/projects/GearBox && grep -c "export function BottomTabBar" src/client/components/BottomTabBar.tsx && grep -c "md:hidden" src/client/components/BottomTabBar.tsx && grep -c "openCatalogSearch" src/client/components/BottomTabBar.tsx && grep -c "openAuthPrompt" src/client/components/BottomTabBar.tsx && grep -c "layers" src/client/lib/iconData.tsx
- src/client/components/BottomTabBar.tsx exists and exports `export function BottomTabBar()`
- File contains `md:hidden` to only show on mobile
- File contains `fixed bottom-0` for fixed positioning
- File contains `z-20` for z-index
- File contains 4 tab items: Home, Collection, Setups, Search (grep for all 4 labels)
- File contains `openCatalogSearch("collection")` for Search tab
- File contains `openAuthPrompt` for anonymous Collection/Setups taps
- File uses `LucideIcon` with names: `home`, `package`, `layers` (or fallback `briefcase`/`grid-2x2`), `search`
- File imports `motion` from `framer-motion` for entry animation
- The `layers` icon exists in `src/client/lib/iconData.tsx` (verified: present)
BottomTabBar renders 4 tabs with Lucide icons on mobile viewports. Search tab opens CatalogSearchOverlay. Collection/Setups tabs fire AuthPromptModal for anonymous users. Active tab is highlighted. Component hidden on md+ screens.
- Both component files exist and export their named functions
- Both use `useMatchRoute` for active route detection
- Both use `openAuthPrompt` for anonymous user interception on protected links
- Both use `openCatalogSearch("collection")` for search trigger
- TopNav uses `hidden md:flex` for desktop nav; BottomTabBar uses `md:hidden` for mobile only
- Neither imports directly from `lucide-react` — both use `LucideIcon` wrapper
- The `layers` icon is available in the curated icon set
- TopNav.tsx is a complete, self-contained component ready to replace TotalsBar in __root.tsx
- BottomTabBar.tsx is a complete, self-contained component ready to add to __root.tsx
- Both handle authenticated and anonymous states correctly
- Both follow existing codebase patterns (Tailwind, LucideIcon, uiStore, useAuth)