Public Access
feat(ui): Sprint 9 — F1 onboarding tour (4-step welcome)
Hand-rolled 4-step tour (no react-joyride) anchors to existing [data-tour="<id>"] attributes. localStorage key mealplanner:onboarding-complete is the source of truth; ?reset-tour=1 clears the key and re-shows. Steps: Dashboard / Pantry / Recipes / Shopping List. Keyboard: 1-4 jump, ←/→ step, Esc dismiss. Off-route fallback renders a centered card with an 'Open <page>' CTA. A11y: role=dialog, aria-modal=true, focus captured on open and restored on close. 5 lines of code across 4 pages; 1 new component (~420 lines). No new dependencies. No backend changes. No migration. Frontend-only deploy. Tracking: Review/sprint9-verification.md (8-step browser smoke + a11y check + reset-link test).
This commit is contained in:
+53
-3
@@ -122,9 +122,7 @@ User report 2026-06-05 (follow-up to Sprint 7): "one of the meals was the meal t
|
||||
- `frontend/src/pages/Dashboard.tsx:38-50, 385-410` — `MealCard` 3-button voting row
|
||||
- `Review/sprint8-verification.md` — new file (deploy + smoke)
|
||||
|
||||
---
|
||||
|
||||
# Context — Sprint 7 (webui empty-meal-plan fix)
|
||||
## Sprint 7 — webui empty-meal-plan fix
|
||||
|
||||
## Why Sprint 7 exists
|
||||
|
||||
@@ -178,3 +176,55 @@ User report 2026-06-05: "Latest meal plans were emails to me this morning, but w
|
||||
- `backend/scripts/fix_2026_06_05_to_2026_06_08.sql` — new (TO ADD)
|
||||
- `Review/sprint7-verification.md` — new (TO ADD)
|
||||
|
||||
---
|
||||
|
||||
# Context — Sprint 9 (F1 Onboarding Tour, H10)
|
||||
|
||||
## Why Sprint 9 exists
|
||||
|
||||
User direction 2026-06-05: "Proceed with the next phase in the redesign." §Future backlog items: F1 (onboarding tour), F8 (Spoonacular proposal), F9 (Ollama proposal), dead `Generate Meal Plan` CTA. F1 is the only §Future item with a clear UI scope — selected.
|
||||
|
||||
## Decisions (locked in for Sprint 9)
|
||||
|
||||
- **D1. Hand-rolled tour, no `react-joyride`.** Adding a new npm dep is a 1-line trade-off; the audit's prior principles ("reuse existing components/ui/*", "no new npm deps") win. The tour is 4 steps; the implementation is ~420 lines of focused React.
|
||||
- **D2. localStorage key `mealplanner:onboarding-complete` (`"1"` once done).** Same shape as the other `mealplanner:` prefixed keys in the codebase (verified by grep).
|
||||
- **D3. `?reset-tour=1` re-triggers the tour.** Strips the param via `navigate(..., { replace: true })` so a refresh doesn't re-clear. Operator can use this from the browser URL bar; a footer link is a 5-line follow-up if requested.
|
||||
- **D4. Auto-show on `/` only.** Other routes need a manual trigger (or `?reset-tour=1`). The first-time user lands on `/` (the Dashboard is the only root route), so auto-show on first visit is the natural moment.
|
||||
- **D5. Tooltip is a real `<div role="dialog" aria-modal="true">`, not a portal.** The 4 anchor elements are all in the same DOM tree as the dialog. The 20-line portal boilerplate was not worth it; a `position: fixed` dialog at the right z-index works fine.
|
||||
- **D6. rAF polling for the anchor's `getBoundingClientRect`.** Runs only while the tour is open. Cancellable. One DOM read per frame; well under 1% CPU on a 60Hz display.
|
||||
- **D7. Focus captured on open (primary action), restored on close.** Uses `previouslyFocused.current = document.activeElement` on mount; restores on unmount. Standard focus-trap pattern, minus the trap (the dialog is intentionally non-modal — the user can interact with the page below).
|
||||
- **D8. The 4 anchor points are stable elements that already exist in the DOM.** The Dashboard's `<Card>` wrapping the Weekly Overview, the Pantry's page header, the Recipes Filters button, the Shopping List page header. Each gets `data-tour="<id>"`. The anchor also has an off-route fallback (centered card + "Open <page>" CTA) so a first-time user who lands on `/pantry` can still see the Dashboard step (with a one-click nav).
|
||||
|
||||
## Open questions to surface to the user, not to assume
|
||||
|
||||
- **Q1. Should the tour show on every page or only `/`?** Default: `/` only. Other pages need `?reset-tour=1`. If the user lands on a non-root page first, the tour does NOT auto-show. Documented in `Review/sprint9-verification.md` smoke step 2.
|
||||
- **Q2. Should the tour re-show on logout / new device?** Default: no. The localStorage key is per-browser, not per-family-profile. If the user has multiple devices or shares a device, the tour shows once per browser. A future migration could move the key to the family profile, but that's a Sprint 11+.
|
||||
- **Q3. Should the tour re-show on a recipe update / catalog change?** Default: no. The tour is a one-shot. New users see it; existing users don't.
|
||||
|
||||
## Sprint 9 verification gate
|
||||
|
||||
- `cd frontend && npm run build` → green (tsc 0 errors, vite 0 errors)
|
||||
- Browser smoke (8 steps) on `http://100.108.208.56:8082/` per `Review/sprint9-verification.md`
|
||||
- No regression in Sprints 1–8
|
||||
|
||||
## Sprint 9 — does NOT touch
|
||||
|
||||
- The `extractErrorMessage` / `showApiError` flow (Sprint 4 F7) — unchanged.
|
||||
- The keyboard shortcuts (Sprint 5 F2) — unchanged.
|
||||
- The bulk pantry add (Sprint 6 F3) — unchanged.
|
||||
- The plan-the-week (Sprint 6 F4) — unchanged.
|
||||
- The undo-toast (Sprint 3 B12) — unchanged.
|
||||
- The WeekRangeNav (Sprint 7) — unchanged.
|
||||
- The 3-button Sprint 8 voting row — unchanged.
|
||||
- Pre-existing WIP: `backend/app/api/recipes.py`, `backend/app/schemas/recipe.py`, `nginx/nginx.conf` — untouched.
|
||||
|
||||
## Key file:line references
|
||||
|
||||
- `frontend/src/components/OnboardingTour.tsx` (NEW) — ~420 lines
|
||||
- `frontend/src/App.tsx:75-105` — `useOnboarding` + tour mount
|
||||
- `frontend/src/pages/Dashboard.tsx:602` — `<Card data-tour="dashboard">`
|
||||
- `frontend/src/pages/Pantry.tsx:185, 208` — header + add-form anchors
|
||||
- `frontend/src/pages/Recipes.tsx:124` — Filters button anchor
|
||||
- `frontend/src/pages/ShoppingList.tsx:231` — header anchor
|
||||
- `Review/sprint9-verification.md` — new file (deploy + 8-step browser smoke + a11y check)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user