Files
Kordant/tasks/shieldai-unified-restructure/04-layout-components.md
2026-05-25 12:23:23 -04:00

4.3 KiB

04. Layout Components — Navbar, Footer, PageContainer, AppShell

meta: id: shieldai-unified-restructure-04 feature: shieldai-unified-restructure priority: P0 depends_on: [shieldai-unified-restructure-01, shieldai-unified-restructure-02, shieldai-unified-restructure-03] tags: [frontend, layout, navigation, solidjs]

objective:

  • Build the structural layout components that wrap every page: a responsive navbar with navigation and auth state, a footer, a page container for consistent padding/max-width, and an AppShell that composes them all with the theme background.

deliverables:

  • web/src/components/layout/Navbar.tsx — Responsive nav with:
    • ShieldAI logo/wordmark (SVG)
    • Navigation links: Features, Pricing, Blog, Dashboard
    • Auth buttons: Sign In (secondary), Get Started (primary)
    • Mobile hamburger menu with slide-out drawer
    • Theme toggle button (light/dark/system)
    • Scroll-aware background blur/glass effect when scrolled
  • web/src/components/layout/Footer.tsx — Multi-column footer with:
    • Logo and tagline
    • Link columns: Product, Company, Resources, Legal
    • Social links (GitHub, Twitter/X, LinkedIn placeholders)
    • Copyright and privacy/terms links
  • web/src/components/layout/PageContainer.tsx — Wrapper with:
    • max-width and centered layout
    • Responsive horizontal padding (px-4 md:px-6 lg:px-8)
    • Optional vertical padding prop
    • class prop for additional overrides
  • web/src/components/layout/AppShell.tsx — Root layout component:
    • Renders <Navbar />, <main>{children}</main>, <Footer />
    • Applies dot-grid background to main content area
    • Handles scroll-to-top on route change
    • Wraps with MetaProvider and Title
  • web/src/components/layout/index.ts — Barrel export.

steps:

  1. Create web/src/components/layout/ directory.
  2. Navbar:
    • Use SolidJS createSignal for mobile menu open state
    • Use onMount + scroll listener to toggle scrolled class for glass effect
    • Logo: create a simple SVG shield icon with gradient fill (reference Lendair's logo approach)
    • Links use <A> from @solidjs/router for SPA navigation
    • Theme toggle uses useTheme() hook from task 02
    • Auth buttons conditionally render based on auth state (stub for now, wire in task 23)
  3. Footer:
    • Grid layout: 4 columns on desktop, 2 on tablet, 1 on mobile
    • Link groups as data arrays mapped with <For>
    • Bottom bar with copyright text
  4. PageContainer:
    • Simple wrapper div with max-w-7xl mx-auto and padding classes
    • Accept class prop and merge with defaults
  5. AppShell:
    • Import MetaProvider, Title from @solidjs/meta
    • Import Navbar, Footer
    • Render children inside <main> with min-h-screen
    • Add onCleanup to remove scroll listener if added in Navbar
    • Use SolidStart root pattern: this becomes the root component passed to <Router>
  6. Wire AppShell into web/src/app.tsx as the Router root.
  7. Create barrel export.

steps:

  • Unit: Navbar renders all links; mobile menu toggles
  • Unit: Footer renders all link columns
  • Unit: PageContainer applies correct max-width and padding classes
  • Unit: AppShell renders Navbar + children + Footer in correct order
  • Visual: Resize browser to verify responsive breakpoints

acceptance_criteria:

  • Navbar is sticky/fixed at top with glass effect on scroll
  • Mobile hamburger menu opens/closes smoothly
  • Theme toggle button changes theme immediately
  • Footer is responsive and all links are clickable
  • PageContainer centers content with consistent padding
  • AppShell wraps all routes correctly via SolidStart root
  • No layout shift on initial load

validation:

  • cd web && pnpm test passes layout tests
  • Open http://localhost:3000 and verify navbar/footer render on all routes
  • Test mobile viewport (<768px) and verify hamburger menu works
  • Toggle theme and verify navbar/footer colors shift correctly

notes:

  • Reference Lendair: ~/code/Lendair/web/src/components/layout/Navbar.tsx, Footer.tsx, PageContainer.tsx
  • The AppShell replaces the current app.tsx Router root. Make sure <FileRoutes /> still works inside it.
  • For auth state in Navbar, create a stub useAuth() hook that returns { isAuthenticated: false } for now; it will be wired to tRPC in task 23.
  • Keep the Navbar height consistent to avoid layout shift when the glass effect activates.