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

90 lines
4.3 KiB
Markdown

# 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.