4.3 KiB
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-widthand centered layout- Responsive horizontal padding (
px-4 md:px-6 lg:px-8) - Optional vertical padding prop
classprop 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
MetaProviderandTitle
- Renders
web/src/components/layout/index.ts— Barrel export.
steps:
- Create
web/src/components/layout/directory. - Navbar:
- Use SolidJS
createSignalfor mobile menu open state - Use
onMount+ scroll listener to togglescrolledclass for glass effect - Logo: create a simple SVG shield icon with gradient fill (reference Lendair's logo approach)
- Links use
<A>from@solidjs/routerfor 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)
- Use SolidJS
- 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
- PageContainer:
- Simple wrapper
divwithmax-w-7xl mx-autoand padding classes - Accept
classprop and merge with defaults
- Simple wrapper
- AppShell:
- Import
MetaProvider,Titlefrom@solidjs/meta - Import
Navbar,Footer - Render children inside
<main>withmin-h-screen - Add
onCleanupto remove scroll listener if added in Navbar - Use SolidStart
rootpattern: this becomes therootcomponent passed to<Router>
- Import
- Wire AppShell into
web/src/app.tsxas the Router root. - 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 testpasses layout tests- Open
http://localhost:3000and 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.tsxRouter 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.