From 6545c2e0d49362e5639f6245b23025f9f965ace6 Mon Sep 17 00:00:00 2001 From: Grok Date: Wed, 17 Jun 2026 13:14:42 -0600 Subject: [PATCH] docs: clarify rollout (no feature flag system) and sheet/dialog approach --- .../2026-06-17-admin-mobile-pwa-design.md | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/superpowers/specs/2026-06-17-admin-mobile-pwa-design.md b/docs/superpowers/specs/2026-06-17-admin-mobile-pwa-design.md index b940f69..de40dd3 100644 --- a/docs/superpowers/specs/2026-06-17-admin-mobile-pwa-design.md +++ b/docs/superpowers/specs/2026-06-17-admin-mobile-pwa-design.md @@ -356,6 +356,15 @@ Editorial-meets-field. Fraunces for numbers, prices, and the few serif headlines - `StickyActionBar` — pending badge, conflict state - `OfflineBanner` — appears on `offline` event, hidden on `online` - `StatusPill` — every status × every color combination renders the right aria-label +- `MoreSheet` — opens via More button, traps focus, closes on Escape and backdrop click, restores focus on close + +**UI primitives:** No dialog/sheet library (vaul, radix, headlessui) is currently in the project. `MoreSheet` and the various bottom sheets (filter, status changer, stock stepper) use the native `` element with `showModal()` + the View Transitions API for open/close animation. This is a deliberate choice to keep the bundle small for the PWA. The native `` is well-supported in Safari 15.4+, Chrome 37+, and Firefox 98+ — all versions we target. + +**Pull-to-refresh:** Custom implementation using pointer events on a sentinel element at the top of each list. We avoid adding a third-party pull-to-refresh library to keep the bundle small. The custom implementation is ~80 lines, respects `overscroll-behavior: contain`, and falls back to no-op if the user has indicated motion sensitivity. + +**Tap-to-call / tap-to-email:** Implemented with explicit `tel:` and `mailto:` URL schemes on `` tags (not buttons that call `window.location`). This ensures the OS handles the routing (e.g., FaceTime prompts on iOS, Gmail/Outlook chooser on Android) and is accessible to screen readers out of the box. + +**Color contrast test exclusions:** `text-faint` is the only token below WCAG AAA (it's 5.3:1, passing AA only). The test in `src/lib/__tests__/design-tokens.test.ts` will assert AAA (7:1) for every token combination *except* `text-faint`, which is tested at AA (4.5:1). This is documented in the test file as an intentional exception. ### E2E (Playwright) @@ -455,18 +464,18 @@ New spec: `tests/mobile-admin/offline-queue.spec.ts` - `src/app/layout.tsx` (PWA meta tags, viewport.fit, themeColor) - `src/components/Providers.tsx` (call `registerServiceWorker()`) - `src/app/admin/layout.tsx` (mount `PWAInstallPrompt` + `OfflineBanner`, swap sidebar for `AdminShell`) -- `src/app/admin/page.tsx` (Dashboard card layout) -- `src/app/admin/orders/page.tsx` (CardList) -- `src/app/admin/orders/[id]/page.tsx` (card layout + StickyActionBar + offline-queue integration) -- `src/app/admin/stops/page.tsx` (time-grouped card list) -- `src/app/admin/products/page.tsx` (image-forward card list) -- `src/app/globals.css` (new type scale, color tokens, spacing) -- `src/styles/admin-design-system.css` (admin-specific tokens) -- `next.config.ts` (cache headers for static assets) +- `src/app/admin/v2/page.tsx` (Dashboard card layout — new v2 route) +- `src/app/admin/v2/orders/page.tsx` (CardList — new v2 route) +- `src/app/admin/v2/orders/[id]/page.tsx` (card layout + StickyActionBar + offline-queue integration — new v2 route) +- `src/app/admin/v2/stops/page.tsx` (time-grouped card list — new v2 route) +- `src/app/admin/v2/products/page.tsx` (image-forward card list — new v2 route) +- `next.config.ts` (cache headers for static assets; cutover redirects in PRs 6 and 8) - `playwright.config.ts` (add `mobile-admin` project at iPhone 13 viewport) - `src/lib/pwa.ts` (small fixes: `load` listener guard, dev-only logging) - `src/app/page.tsx` (favicon ref fix) +Note: the v1 admin pages (`src/app/admin/page.tsx`, `src/app/admin/orders/page.tsx`, etc.) are **not** modified by PRs 1–5. They continue to serve the existing desktop layout until the cutover PRs redirect their routes to v2. After cutover, the v1 files are deleted in a follow-up commit. + --- ## Open questions (deferred) @@ -489,14 +498,25 @@ New spec: `tests/mobile-admin/offline-queue.spec.ts` ## Rollout plan +> **Note on feature flags:** The project has a `src/lib/feature-flags.ts` system, but it's for **brand-scoped add-on features** (Harvest Reach, Square Sync, etc.), not for app-wide UI rollouts. There is no general-purpose feature flag system in this codebase. We will use a **route-based dual-deployment** strategy for rollout: +> +> - PRs 1–2 (design system + PWA scaffolding) are non-breaking; they add the new infrastructure without changing existing routes. +> - PRs 3–5 (Orders, Stops, Products) ship the new mobile-first versions at **`/admin/v2/orders`**, **`/admin/v2/stops`**, **`/admin/v2/products`**, and **`/admin/v2/orders/[id]`** initially. The old `/admin/orders` etc. routes continue to work unchanged. Internal team dogfoods at `/admin/v2/*` for 1–2 weeks. +> - PR 6 cuts over: a redirect in `next.config.ts` sends `/admin/orders*` → `/admin/v2/orders*`, etc. The old routes are removed in a follow-up commit. +> - PR 7 (Dashboard at `/admin/v2`) follows the same pattern. +> +> This avoids the need to introduce a feature flag system, which would be a separate piece of work. + 1. **PR 1 — Design system + admin shell** — type scale, color tokens, AdminShell, MobileTabBar, MoreSheet, offline queue + sync. No page changes yet. Lighthouse PWA gate added. 2. **PR 2 — PWA manifest + SW + icons + offline page** — PWA installable, splash, themed status bar. All tests pass. -3. **PR 3 — Orders (list + detail)** — first page on the new design language. Validates the components in real use. -4. **PR 4 — Stops** -5. **PR 5 — Products** -6. **PR 6 — Dashboard** (depends on the new `get_dashboard_summary` RPC migration) +3. **PR 3 — Orders v2 (list + detail)** at `/admin/v2/orders/*` — first page on the new design language. Validates the components in real use. +4. **PR 4 — Stops v2** at `/admin/v2/stops` +5. **PR 5 — Products v2** at `/admin/v2/products` +6. **PR 6 — Cutover Orders + Stops + Products** — redirects in `next.config.ts`; old routes removed in a follow-up commit +7. **PR 7 — Dashboard v2** at `/admin/v2` (depends on the new `get_dashboard_summary` RPC migration) +8. **PR 8 — Dashboard cutover** — redirect `/admin` → `/admin/v2`; remove old dashboard -Each PR is independently shippable behind a feature flag (`ADMIN_MOBILE_V2`) so we can dogfood it internally before cutting over. The desktop layout is never affected until the flag is on for everyone. +Each PR is independently shippable and reversible. The desktop layout is never affected until cutover PRs land. ---