Files
MealQuest/web/src/shell/navItems.ts
T
dev_agentandClaude Opus 5.5 93e209c302
CI / ci (pull_request) Successful in 1m31s
CI / ci (push) Successful in 1m32s
Add responsive app shell, routes and navigation
Replace the catch-all placeholder with an AppShell that renders one
primary nav per breakpoint (chosen with matchMedia via useBreakpoint):
a dark pill bottom bar below 768 px, a 96 px rail with the "M" mark at
768-1199 px, and a 208 px sidebar with the MealQuest wordmark and the
"Our kitchen / Shared household" card at 1200 px and up. Nav order is
Home, Plan, Discover, Quick, Settings; NavLink marks the active item
aria-current="page", with nested Plan and Settings paths keeping their
parent current. The mobile scroll area reserves 100 px plus the safe
area beneath its content.

Register every handoff route plus /settings/household,
/settings/regulars and /settings/calendar, each with a placeholder
heading. Remove the default body margin so the shell fills the viewport.

Tests force each breakpoint with a matchMedia mock and assert the
routes, nav order, each layout's structure, aria-current and the
mobile bottom padding from the stylesheet.

Maestro task: 42a4695a-6bd0-49a1-925e-387858dbee48

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 18:33:09 -04:00

21 lines
760 B
TypeScript

import type { LucideIcon } from 'lucide-react'
import { Calendar, Compass, House, SlidersHorizontal, Zap } from 'lucide-react'
export type NavItem = {
to: string
label: string
icon: LucideIcon
// Match the path exactly; otherwise nested paths (/plan/shopping,
// /settings/ai) also mark the item current.
end: boolean
}
// The primary nav, in the same order in every layout.
export const navItems: readonly NavItem[] = [
{ to: '/', label: 'Home', icon: House, end: true },
{ to: '/plan', label: 'Plan', icon: Calendar, end: false },
{ to: '/discover', label: 'Discover', icon: Compass, end: false },
{ to: '/quick', label: 'Quick', icon: Zap, end: false },
{ to: '/settings', label: 'Settings', icon: SlidersHorizontal, end: false },
]