12 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 27-top-nav-restructure-and-search-bar-rethink | 03 | execute | 2 |
|
|
false |
|
|
Purpose: This is the integration plan that connects everything built in Plans 01 and 02. The TotalsBar is swapped for TopNav, BottomTabBar is added for mobile, the FAB gets hidden on mobile (per D-15), the landing page hero is removed (per D-09/D-10), and /setups is added to isPublicRoute so anonymous direct navigation works.
Output: Fully wired navigation system visible across the app.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.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 @.planning/phases/27-top-nav-restructure-and-search-bar-rethink/27-01-SUMMARY.md @.planning/phases/27-top-nav-restructure-and-search-bar-rethink/27-02-SUMMARY.md From src/client/components/TopNav.tsx: ```typescript export function TopNav(): JSX.Element; // Persistent top nav bar with logo, nav links, search, user menu // Handles auth interception internally ```From src/client/components/BottomTabBar.tsx:
export function BottomTabBar(): JSX.Element;
// Mobile bottom tab bar, renders only on md:hidden
// Handles auth interception internally
From src/client/routes/__root.tsx:
// Current imports to change:
import { TotalsBar } from "../components/TotalsBar"; // REMOVE
// Current isPublicRoute check:
const isPublicRoute =
location.pathname === "/" ||
location.pathname.startsWith("/users/") ||
location.pathname.startsWith("/global-items") ||
location.pathname.startsWith("/setups/") ||
location.pathname === "/login";
// Current FAB render:
{showFab && <FabMenu isSetupsPage={isSetupsPage} />}
// Current TotalsBar render:
<TotalsBar {...totalsBarProps} />
1. Update imports:
- Remove:
import { TotalsBar } from "../components/TotalsBar"; - Add:
import { TopNav } from "../components/TopNav"; - Add:
import { BottomTabBar } from "../components/BottomTabBar";
2. Remove TotalsBar-related code in RootLayout:
- Delete the
isDashboardvariable:const isDashboard = !!matchRoute({ to: "/" }); - Delete the
totalsBarPropsvariable:const totalsBarProps = isDashboard ? {} : { linkTo: "/" };
3. Replace TotalsBar render with TopNav:
Change <TotalsBar {...totalsBarProps} /> to <TopNav />
4. Add /setups to isPublicRoute (pitfall 2 from research):
The current check has location.pathname.startsWith("/setups/") which only covers /setups/123 detail pages. Add location.pathname === "/setups" so the index route is also public:
const isPublicRoute =
location.pathname === "/" ||
location.pathname.startsWith("/users/") ||
location.pathname.startsWith("/global-items") ||
location.pathname === "/setups" ||
location.pathname.startsWith("/setups/") ||
location.pathname === "/login";
5. Hide FAB on mobile (per D-15):
Wrap the FabMenu in a div with hidden md:block:
{showFab && (
<div className="hidden md:block">
<FabMenu isSetupsPage={isSetupsPage} />
</div>
)}
6. Add BottomTabBar:
Add <BottomTabBar /> after the FabMenu block (before CatalogSearchOverlay). It renders itself only on mobile via md:hidden.
7. Add bottom padding for mobile tab bar (pitfall from research):
On the root div <div className="min-h-screen bg-gray-50">, add mobile-only bottom padding so content isn't obscured by the fixed bottom tab bar:
<div className="min-h-screen bg-gray-50 pb-16 md:pb-0">
pb-16 (64px) accounts for the bottom tab bar height on mobile. md:pb-0 removes it on desktop.
Do NOT change: CandidateDeleteDialog, ResolveDialog, CatalogSearchOverlay, AddToCollectionModal, AddToThreadModal, Toaster, AuthPromptModal, OnboardingWizard, ConfirmDialog, ExternalLinkDialog, or any other existing modal/dialog code.
cd /home/jean-luc-makiola/Development/projects/GearBox && grep -c "TopNav" src/client/routes/__root.tsx && grep -c "BottomTabBar" src/client/routes/__root.tsx && ! grep -q "TotalsBar" src/client/routes/__root.tsx && echo "no-totalsbar" && grep -c 'hidden md:block' src/client/routes/__root.tsx && grep 'isPublicRoute' src/client/routes/__root.tsx | grep -c '/setups"' && grep -c 'pb-16 md:pb-0' src/client/routes/__root.tsx
<acceptance_criteria>
- __root.tsx imports TopNav from ../components/TopNav (not TotalsBar)
- __root.tsx imports BottomTabBar from ../components/BottomTabBar
- __root.tsx does NOT contain TotalsBar anywhere
- __root.tsx does NOT contain isDashboard or totalsBarProps variables
- __root.tsx renders <TopNav /> (no props)
- __root.tsx renders <BottomTabBar />
- FabMenu is wrapped in <div className="hidden md:block">
- isPublicRoute includes location.pathname === "/setups"
- Root div has pb-16 md:pb-0 classes for mobile bottom padding
- All existing modals/dialogs remain unchanged
</acceptance_criteria>
Root layout uses TopNav instead of TotalsBar, BottomTabBar is rendered for mobile, FAB is hidden on mobile, /setups is a public route, and mobile bottom padding prevents content occlusion.
Changes:
-
Delete the
HeroSectionfunction entirely (lines ~35-72 in current file). This includes the heading "Discover Gear", subtitle, search bar div, and "Go to Collection" link. -
Remove unused imports:
- Remove
{ Search } from "lucide-react"— only used by HeroSection - Remove
{ Link } from "@tanstack/react-router"— only used by HeroSection's "Go to Collection" link (check if Link is used elsewhere in the file first; it is not) - Remove
useAuthimport — only used to passisAuthenticatedto HeroSection - Remove
useUIStoreimport — only used to getopenCatalogSearchfor HeroSection
- Remove
-
Update LandingPage function to remove HeroSection render and unused variables:
function LandingPage() {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<PopularSetupsSection />
<RecentItemsSection />
<TrendingCategoriesSection />
</div>
);
}
- Keep unchanged:
PopularSetupsSection,RecentItemsSection,TrendingCategoriesSection,SectionSkeleton, all discovery hooks imports,GlobalItemCardimport,PublicSetupCardimport, and thecreateFileRouteroute definition. cd /home/jean-luc-makiola/Development/projects/GearBox && ! grep -q "HeroSection" src/client/routes/index.tsx && echo "no-hero" && ! grep -q "Discover Gear" src/client/routes/index.tsx && echo "no-heading" && ! grep -q "lucide-react" src/client/routes/index.tsx && echo "no-lucide-direct" && grep -c "PopularSetupsSection" src/client/routes/index.tsx && ! grep -q "useAuth" src/client/routes/index.tsx && echo "no-useAuth" && ! grep -q "useUIStore" src/client/routes/index.tsx && echo "no-useUIStore" <acceptance_criteria>- src/client/routes/index.tsx does NOT contain
HeroSection(function definition or usage) - src/client/routes/index.tsx does NOT contain
Discover Gearheading text - src/client/routes/index.tsx does NOT contain
Go to Collectionlink text - src/client/routes/index.tsx does NOT import from
lucide-react - src/client/routes/index.tsx does NOT import
useAuth - src/client/routes/index.tsx does NOT import
useUIStore - LandingPage function renders PopularSetupsSection as first child
- PopularSetupsSection, RecentItemsSection, TrendingCategoriesSection all remain
- SectionSkeleton helper function remains </acceptance_criteria> Landing page starts directly with Popular Setups section. No hero section, no heading, no search bar, no "Go to Collection" link. No unused imports (useAuth, useUIStore, lucide-react). Search is now exclusively in the TopNav bar.
- src/client/routes/index.tsx does NOT contain
<success_criteria>
- Complete navigation flow works on both desktop and mobile viewports
- All 17 locked decisions (D-01 through D-17) are satisfied
- No visual regressions on existing pages
- No console errors </success_criteria>