# Sprint 9 — F1 Onboarding Tour (H10) **Status (2026-06-05):** ✅ Code complete. `npm run build` green. Awaiting user commit + deploy. **Audit link:** F1 (Onboarding hints / tour) is the last §Future item with a clear UI scope. F8 (Spoonacular) and F9 (Ollama) are full backend proposals; the dead `Generate Meal Plan` CTA is a separate follow-up. **Goal:** First-time visitors get a 4-step tour. Returning users never see it. The tour re-shows on demand via `?reset-tour=1`. --- ## What ships ### `OnboardingTour.tsx` (NEW) Hand-rolled (no `react-joyride`) to keep the npm footprint flat. 4 steps: 1. **Dashboard** — "Your weekly meal plan" 2. **Pantry** — "What you have in stock" 3. **Recipes** — "Browse + filter recipes" 4. **Shopping List** — "Plan → shop → restock" Each step: - Anchors to a `[data-tour=""]` attribute on the existing page. - Renders a tooltip card pinned to the anchor (top/bottom/center fallback). - Highlights the anchor with a primary-400 ring + soft scrim. - Step progress shown as 4 progress bars (top of card). - Skip / Back / Next (or "Got it" on the last step). **Keyboard nav (when tour is visible):** - `1`–`4` → jump to that step - `←/→` → step back / forward - `Esc` → dismiss - Tab order: `Skip → Back → Next` (or `Skip → Open page → Next` when off-route) **A11y:** - `role="dialog"`, `aria-modal="true"`, `aria-labelledby` → step title. - Focus is captured on open (moved to the primary action) and restored on close. - Tooltip + anchor ring are announced via `aria-hidden="true"` (decorative); the dialog text is the real signal. **Storage:** - localStorage key: `mealplanner:onboarding-complete` (`"1"` once completed). - `?reset-tour=1` in any URL clears the key + strips the param via `navigate(..., { replace: true })` so a refresh doesn't re-clear. - Reading the key is wrapped in try/catch — private mode / disabled storage silently falls through. ### Anchor points (5 lines of code total) | Page | File:line | Anchor | Notes | |---|---|---|---| | Dashboard | `pages/Dashboard.tsx:602` | `` | The Weekly Overview grid; the most-confused first-time surface. | | Pantry | `pages/Pantry.tsx:185` (header) + `:208` (add form, when open) | `
` | Header is always present; the add-form card adds a second anchor when the form is open. | | Recipes | `pages/Recipes.tsx:124` (Filters button) | `