Epic: v4 — Mobile-first UI/UX overhaul #96

Open
opened 2026-07-22 04:35:24 +00:00 by steve · 5 comments
Owner

Tracking epic. Functionally pansy is there (v1–v3 shipped), but the UI is desktop-shaped and cramped on a phone. This epic makes pansy mobile-first: designed for a ~390px screen first, desktop as the enhancement.

What's wrong today (audit + live mobile screenshots)

Audited the whole web/src tree and drove the built app at 390px. The findings:

  • The garden editor wastes the phone. The control column (title, Share, Season, a 7-chip object palette that wraps to 3 rows, Journal, History, Assistant) stacks above the canvas and eats ~55% of the viewport, squeezing the actual garden — the whole point of the app — into a short strip at the bottom.
  • No single "mode" model. The four core activities are governed by three different surfaces: the palette (place fixtures), a separate focus-mode toolbar + seed tray (place plants), and the rail tabs (journal / history / assistant / inspector). There is no one easy toggle for "I'm placing beds" vs "I'm planting" vs "journaling" vs "assistant."
  • Selecting a bed hides the garden. On mobile the inspector opens as a bottom sheet that covers the canvas entirely — you can't see what you're planting into while you inspect/plant it.
  • No mobile navigation. The top bar is desktop-style (links wrap, "Sign out" breaks to two lines); there's no bottom tab bar and no back-to-gardens affordance in the editor.
  • No "resume where I was." / always dumps you on the gardens list; the device doesn't remember the garden you were just in.
  • No recent-plants quick access beyond a manual per-garden seed tray (insertion-ordered, not usage-ranked).
  • Touch ergonomics fall short: 12px object resize/rotate handles, keyboard-only fine nudging, ~24px close buttons, toast stack renders over the open rail sheet.
  • Perf: one >500 KB JS chunk, no route-level code splitting — a slow first paint on mobile data.
  • Carried in from v3: the seed-packet scan UI and fill-mode (clump/grid) toggle were built backend-only and need their mobile UI; EXIF orientation for phone photos.

Principles

  • Mobile-first, not mobile-also. Design each screen for 390px, then enhance for md:+.
  • The canvas is the hero. In the editor the garden fills the screen; tools dock into a slim, mode-specific bottom bar — never a top-stacked column that shoves the garden off-screen.
  • One primary mode switch in the editor: Fixtures · Plants · Journal · Assistant.
  • Keep the good foundation. Tokens (@theme), bottom-sheet Modal, dvh, touch-action, and the clean component split stay — this is a restructure, not a rewrite. No backend/service contract changes except the two carried features.
  • One Gadfly sweep per PR, fix what's real, merge on green. Docs (README/DESIGN) updated in the same PR when behavior changes.

Issues (dependency order)

Foundation (independent, quick wins)

  • #97 — Resume the last garden on this device
  • #98 — Mobile app shell: bottom tab nav + slim top bar

Editor restructure (the core)

  • #99 — Editor mode model + mobile layout restructure (Fixtures · Plants · Journal · Assistant) — backbone; #100/#101 depend on it
  • #100 — Plants mode: recent-plants quick strip + clump/grid fill toggle (carries #77 UI)
  • #101 — Non-occluding mobile inspector (object + plop)

Carried features (independent)

  • #102 — Seed-packet scan UI: camera/upload → proposal → confirm (carries #81 UI)
  • #103 — EXIF orientation when normalizing uploaded images (carries #81 EXIF)

Polish & perf (independent)

  • #104 — Touch ergonomics: handles, on-screen nudge, tap targets, sheet/toast z-index
  • #105 — Responsive polish on non-editor pages (gardens list, plants, settings, modals)
  • #106 — Route-level code splitting for faster mobile first paint
  • #107 — Cleanup: dead PageStub, ConfirmModal, editor max-width

Rough build order: #97#98#99 → (#100, #101) → #102/#103/#104/#105/#106/#107 as they slot in. Each is one PR.

Open questions (deferred to the end, per Steve)

Collected as they come up during implementation, to resolve in one pass rather than blocking overnight work:

  • #99/#100 interaction shape: the plan replaces "focus a bed → floating toolbar" with "Plants mode + a selected bed," and "recent plants" = recently-planted-in-this-garden. Both are reasonable defaults I'll build to; worth a look on a real phone to confirm they read right.
  • Whether the editor's bottom mode bar should also expose Fixtures/Plants on desktop as a segmented control, or keep desktop's side-rail layout.
Tracking epic. Functionally pansy is there (v1–v3 shipped), but the UI is desktop-shaped and cramped on a phone. This epic makes pansy **mobile-first**: designed for a ~390px screen first, desktop as the enhancement. ## What's wrong today (audit + live mobile screenshots) Audited the whole `web/src` tree and drove the built app at 390px. The findings: - **The garden editor wastes the phone.** The control column (title, Share, Season, a 7-chip object palette that wraps to 3 rows, Journal, History, Assistant) stacks *above* the canvas and eats ~55% of the viewport, squeezing the actual garden — the whole point of the app — into a short strip at the bottom. - **No single "mode" model.** The four core activities are governed by *three different surfaces*: the palette (place fixtures), a separate focus-mode toolbar + seed tray (place plants), and the rail tabs (journal / history / assistant / inspector). There is no one easy toggle for "I'm placing beds" vs "I'm planting" vs "journaling" vs "assistant." - **Selecting a bed hides the garden.** On mobile the inspector opens as a bottom sheet that covers the canvas entirely — you can't see what you're planting into while you inspect/plant it. - **No mobile navigation.** The top bar is desktop-style (links wrap, "Sign out" breaks to two lines); there's no bottom tab bar and no back-to-gardens affordance in the editor. - **No "resume where I was."** `/` always dumps you on the gardens list; the device doesn't remember the garden you were just in. - **No recent-plants quick access** beyond a manual per-garden seed tray (insertion-ordered, not usage-ranked). - **Touch ergonomics fall short:** 12px object resize/rotate handles, keyboard-only fine nudging, ~24px close buttons, toast stack renders over the open rail sheet. - **Perf:** one >500 KB JS chunk, no route-level code splitting — a slow first paint on mobile data. - Carried in from v3: the **seed-packet scan UI** and **fill-mode (clump/grid) toggle** were built backend-only and need their mobile UI; **EXIF orientation** for phone photos. ## Principles - **Mobile-first, not mobile-also.** Design each screen for 390px, then enhance for `md:`+. - **The canvas is the hero.** In the editor the garden fills the screen; tools dock into a slim, mode-specific bottom bar — never a top-stacked column that shoves the garden off-screen. - **One primary mode switch** in the editor: Fixtures · Plants · Journal · Assistant. - **Keep the good foundation.** Tokens (`@theme`), bottom-sheet `Modal`, `dvh`, `touch-action`, and the clean component split stay — this is a restructure, not a rewrite. No backend/service contract changes except the two carried features. - One Gadfly sweep per PR, fix what's real, merge on green. Docs (README/DESIGN) updated in the same PR when behavior changes. ## Issues (dependency order) **Foundation (independent, quick wins)** - [ ] #97 — Resume the last garden on this device - [ ] #98 — Mobile app shell: bottom tab nav + slim top bar **Editor restructure (the core)** - [ ] #99 — Editor mode model + mobile layout restructure (Fixtures · Plants · Journal · Assistant) — *backbone; #100/#101 depend on it* - [ ] #100 — Plants mode: recent-plants quick strip + clump/grid fill toggle (carries #77 UI) - [ ] #101 — Non-occluding mobile inspector (object + plop) **Carried features (independent)** - [ ] #102 — Seed-packet scan UI: camera/upload → proposal → confirm (carries #81 UI) - [ ] #103 — EXIF orientation when normalizing uploaded images (carries #81 EXIF) **Polish & perf (independent)** - [ ] #104 — Touch ergonomics: handles, on-screen nudge, tap targets, sheet/toast z-index - [ ] #105 — Responsive polish on non-editor pages (gardens list, plants, settings, modals) - [ ] #106 — Route-level code splitting for faster mobile first paint - [ ] #107 — Cleanup: dead PageStub, ConfirmModal, editor max-width Rough build order: #97 → #98 → #99 → (#100, #101) → #102/#103/#104/#105/#106/#107 as they slot in. Each is one PR. ## Open questions (deferred to the end, per Steve) Collected as they come up during implementation, to resolve in one pass rather than blocking overnight work: - **#99/#100 interaction shape:** the plan replaces "focus a bed → floating toolbar" with "Plants mode + a selected bed," and "recent plants" = recently-planted-in-*this-garden*. Both are reasonable defaults I'll build to; worth a look on a real phone to confirm they read right. - Whether the editor's bottom mode bar should also expose Fixtures/Plants on desktop as a segmented control, or keep desktop's side-rail layout.
steve added the epicfrontend labels 2026-07-22 04:35:24 +00:00
Author
Owner

Progress (overnight):

  • #97 merged (#108) — / resumes the device's last garden; stale ids self-clear.
  • #98 merged (#109) — mobile bottom tab bar + slim top bar + account menu; editor & public-garden routes suppress the bar.

Both took one Gadfly sweep, fixed the real findings, merged on green. Next up: the backbone, #99 (editor mode model).

Progress (overnight): - ✅ **#97** merged (#108) — `/` resumes the device's last garden; stale ids self-clear. - ✅ **#98** merged (#109) — mobile bottom tab bar + slim top bar + account menu; editor & public-garden routes suppress the bar. Both took one Gadfly sweep, fixed the real findings, merged on green. Next up: the backbone, **#99** (editor mode model).
Author
Owner

Progress (cont.):

  • #99 merged (#110) — the editor mode bar (Fixtures · Plants · Journal · Assistant); on a phone the canvas is now the whole screen. Verified live.
  • #103 merged (#111) — EXIF orientation baked in at normalize, so phone photos aren't sideways.

Four merged so far (#97, #98, #99, #103), each one Gadfly sweep → fix → merge on green. Next: #100 (recent-plants quick strip + fill toggle), which builds on the #99 Plants mode.

Progress (cont.): - ✅ **#99** merged (#110) — the editor **mode bar** (Fixtures · Plants · Journal · Assistant); on a phone the canvas is now the whole screen. Verified live. - ✅ **#103** merged (#111) — EXIF orientation baked in at normalize, so phone photos aren't sideways. Four merged so far (#97, #98, #99, #103), each one Gadfly sweep → fix → merge on green. Next: **#100** (recent-plants quick strip + fill toggle), which builds on the #99 Plants mode.
Author
Owner

Overnight status — all four explicit asks delivered

Merged tonight (5 PRs, each one Gadfly sweep → fix → merge on green, all verified live at 390px):

  • #97 — resume the last garden on this device
  • #98 — mobile bottom-tab shell + slim top bar + account menu
  • #99 — editor mode bar (Fixtures · Plants · Journal · Assistant); the canvas is now the whole phone screen
  • #100 — Plants mode recent-planted quick strip + clump/rows fill (finally a UI for the #77 grid fill)
  • #103 — EXIF orientation baked in so phone photos aren't sideways

That covers everything you named directly: mobile-first, resume-the-garden, the one-tap mode toggle, and recently-planted quick access — plus EXIF and the fill UI as bonuses off the same work.

Remaining, queued for the next run:

  • ⏭️ #102 — seed-packet scan UI. Built the whole backend for this (#94), but the UI needs a vision-model-configured instance to verify end-to-end, which the local dev box doesn't have (no OLLAMA_CLOUD_API_KEY). Deliberately deferred so it lands where I can actually test the camera → proposal → confirm flow against a real model, rather than ship it blind.
  • ⏭️ #101 non-occluding mobile inspector · #104 touch ergonomics · #105 responsive polish on non-editor pages · #106 route code-splitting · #107 cleanup (dead PageStub, ConfirmModal, editor max-width)

Two design calls I made and would like a second look at on your phone (deferred per your ask — see the questions I'm surfacing at the end of the session): the Plants-mode interaction (focus a bed → tray appears; journal/assistant slide a sheet over the mode bar), and "recent" meaning recently-planted-in-this-garden.

## Overnight status — all four explicit asks delivered **Merged tonight (5 PRs, each one Gadfly sweep → fix → merge on green, all verified live at 390px):** - ✅ **#97** — resume the last garden on this device - ✅ **#98** — mobile bottom-tab shell + slim top bar + account menu - ✅ **#99** — editor **mode bar** (Fixtures · Plants · Journal · Assistant); the canvas is now the whole phone screen - ✅ **#100** — Plants mode **recent-planted quick strip** + clump/**rows** fill (finally a UI for the #77 grid fill) - ✅ **#103** — EXIF orientation baked in so phone photos aren't sideways That covers everything you named directly: mobile-first, resume-the-garden, the one-tap mode toggle, and recently-planted quick access — plus EXIF and the fill UI as bonuses off the same work. **Remaining, queued for the next run:** - ⏭️ **#102 — seed-packet scan UI.** Built the whole backend for this (#94), but the *UI* needs a **vision-model-configured instance to verify end-to-end**, which the local dev box doesn't have (no `OLLAMA_CLOUD_API_KEY`). Deliberately deferred so it lands where I can actually test the camera → proposal → confirm flow against a real model, rather than ship it blind. - ⏭️ **#101** non-occluding mobile inspector · **#104** touch ergonomics · **#105** responsive polish on non-editor pages · **#106** route code-splitting · **#107** cleanup (dead PageStub, ConfirmModal, editor max-width) **Two design calls I made and would like a second look at on your phone** (deferred per your ask — see the questions I'm surfacing at the end of the session): the Plants-mode interaction (focus a bed → tray appears; journal/assistant slide a sheet over the mode bar), and "recent" meaning recently-planted-*in-this-garden*.
Author
Owner

End-of-run status — 6 of 11 merged

Merged tonight (all verified live at 390px, one Gadfly sweep → fix → merge each):

  • #97 resume last garden · #98 mobile shell · #99 editor mode bar · #100 recent-planted strip + fill toggle · #103 EXIF orientation · #106 route code-splitting (app entry chunk 578 KB → 39 KB, editor now lazy)

Left for the next run (all well-specified above):

  • #101 non-occluding mobile inspector — highest-value remaining (selecting a bed still covers the canvas)
  • #102 seed-packet scan UI — held: needs a vision-model-configured instance to verify the camera→proposal→confirm flow end-to-end (local box has no OLLAMA_CLOUD_API_KEY)
  • #104 touch ergonomics · #105 responsive polish (non-editor pages) · #107 cleanup (dead PageStub, ConfirmModal, editor max-width)

Stopping here rather than rushing the remaining editor/inspector work at the tail of a long session. Two design calls I'd like your eyes on are in the questions I'm surfacing now (deferred per your ask).

### End-of-run status — 6 of 11 merged **Merged tonight (all verified live at 390px, one Gadfly sweep → fix → merge each):** - ✅ #97 resume last garden · ✅ #98 mobile shell · ✅ #99 editor mode bar · ✅ #100 recent-planted strip + fill toggle · ✅ #103 EXIF orientation · ✅ #106 route code-splitting (app entry chunk 578 KB → 39 KB, editor now lazy) **Left for the next run** (all well-specified above): - #101 non-occluding mobile inspector — highest-value remaining (selecting a bed still covers the canvas) - #102 seed-packet scan UI — **held**: needs a vision-model-configured instance to verify the camera→proposal→confirm flow end-to-end (local box has no `OLLAMA_CLOUD_API_KEY`) - #104 touch ergonomics · #105 responsive polish (non-editor pages) · #107 cleanup (dead PageStub, ConfirmModal, editor max-width) Stopping here rather than rushing the remaining editor/inspector work at the tail of a long session. Two design calls I'd like your eyes on are in the questions I'm surfacing now (deferred per your ask).
Author
Owner

Near-complete — 10 of 11 merged

Picked back up after your two answers (always-visible mode bar + do #101 next) and carried the rest of the epic through:

  • #101 (#114) — non-occluding mobile inspector + always-visible mode bar (your call): the rail is now an in-flow peek between the canvas and the mode bar, so selecting a bed keeps the garden visible and you can switch modes without closing a panel.
  • #105 (#115) — touch-sized the gardens/plants card actions.
  • #106 (#113) — route code-splitting (app entry chunk 578 KB → 39 KB).
  • #107 (#116) — ConfirmModal primitive (5 dialogs deduped), dead PageStub removed, full-width desktop editor.
  • #104 (#117) — bigger touch handles + an on-screen 1cm nudge pad (shares the keyboard nudge's debounced-commit).

Everything is merged and main is green (Go + web build/test all pass, no chunk warning), so it's deploying to the live instance now.

One issue held: #102 (seed-packet scan UI)

The only one not done. I built its whole backend already (#94), but the UI needs a vision-model-configured instance to verify end-to-end (camera → proposal → confirm), and the local box has no OLLAMA_CLOUD_API_KEY. I didn't want to ship a camera-capture feature I couldn't actually test against a real model. It's fully specced and ready to build the moment it can be verified where the vision model runs (the live instance).

Leaving this epic open for #102; everything else is done.

## Near-complete — 10 of 11 merged Picked back up after your two answers (always-visible mode bar + do #101 next) and carried the rest of the epic through: - ✅ **#101** (#114) — non-occluding mobile inspector **+ always-visible mode bar** (your call): the rail is now an in-flow *peek* between the canvas and the mode bar, so selecting a bed keeps the garden visible and you can switch modes without closing a panel. - ✅ **#105** (#115) — touch-sized the gardens/plants card actions. - ✅ **#106** (#113) — route code-splitting (app entry chunk 578 KB → 39 KB). - ✅ **#107** (#116) — `ConfirmModal` primitive (5 dialogs deduped), dead `PageStub` removed, full-width desktop editor. - ✅ **#104** (#117) — bigger touch handles + an on-screen 1cm nudge pad (shares the keyboard nudge's debounced-commit). **Everything is merged and `main` is green** (Go + web build/test all pass, no chunk warning), so it's deploying to the live instance now. ### One issue held: #102 (seed-packet scan UI) The only one not done. I built its whole backend already (#94), but the **UI needs a vision-model-configured instance to verify end-to-end** (camera → proposal → confirm), and the local box has no `OLLAMA_CLOUD_API_KEY`. I didn't want to ship a camera-capture feature I couldn't actually test against a real model. It's fully specced and ready to build the moment it can be verified where the vision model runs (the live instance). Leaving this epic open for #102; everything else is done.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/pansy#96