Editor mode model: mobile Fixtures/Plants/Journal/Assistant bar (#99)
Build image / build-and-push (push) Successful in 10s
Gadfly review (reusable) / review (pull_request) Successful in 8m55s
Adversarial Review (Gadfly) / review (pull_request) Successful in 8m56s

On a phone the editor stacked a control column (title, share, season, a
7-chip palette wrapping to 3 rows, journal/history/assistant) ABOVE the
canvas, crushing the garden — the point of the app — into a short strip.
There was no single "mode" switch: fixtures lived in the palette, plants
in a floating focus toolbar, and journal/assistant in the rail.

Mobile-first now (#99): the canvas is the whole screen, and a bottom mode
bar switches the tools docked beneath it —
- Fixtures  → the object palette (arm → tap to place)
- Plants    → the seed tray, once a bed is focused; focusing a bed enters
              this mode. No bed focused → a "tap a bed, then Plant here"
              hint. Done planting / Clear ride along.
- Journal   → opens the journal rail sheet
- Assistant → opens the chat rail sheet (hidden with no model configured)

A slim mobile top strip keeps the garden name / season / share that lived
in the desktop column. Closing a panel rail returns to a canvas mode so
the bar reappears; History stays a rail sub-tab (not a fifth mode).

Desktop is untouched: the mode bar is md:hidden and the side-column layout
stands; `mode` is an inert hint there. Store gains `mode`/`setMode`
(reset with the rest of transient state on garden switch).

Verified live at 390px (each mode + the select-bed → Plant here → seed-tray
flow, canvas now dominant) and 1280px (desktop unchanged). tsc + vitest
(92) + build green. DESIGN.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
This commit is contained in:
2026-07-22 01:16:44 -04:00
co-authored by Claude Opus 4.8
parent 8a27df9e9c
commit 9ec626302b
3 changed files with 169 additions and 5 deletions
+16
View File
@@ -11,10 +11,22 @@ import type { EditorObject } from './types'
export const MIN_SCALE = 0.05 // px per cm — fully zoomed out
export const MAX_SCALE = 20 // px per cm — fully zoomed in
// The editor's one primary activity (#99). On mobile this is the segmented
// control at the bottom of the screen; it decides which tools dock there —
// placing fixtures, placing plants, the journal, or the assistant — so the four
// activities stop competing for the same cramped strip. Desktop keeps its
// side-column layout and treats this as a lighter hint.
export type EditorMode = 'fixtures' | 'plants' | 'journal' | 'assistant'
interface EditorState {
viewport: Viewport
setViewport: (next: Viewport | ((prev: Viewport) => Viewport)) => void
// The primary editor mode (mobile mode bar). Ephemeral — which tool you were
// last using is not a property of the garden.
mode: EditorMode
setMode: (mode: EditorMode) => void
// The selected object OR plop (mutually exclusive; selecting one clears the
// other). selectedId is a garden object; selectedPlantingId is a plop.
selectedId: number | null
@@ -82,6 +94,9 @@ export const useEditorStore = create<EditorState>((set) => ({
viewport: { tx: 0, ty: 0, scale: 1 },
setViewport: (next) => set((s) => ({ viewport: typeof next === 'function' ? next(s.viewport) : next })),
mode: 'fixtures',
setMode: (mode) => set({ mode }),
selectedId: null,
select: (id) => set({ selectedId: id, selectedPlantingId: null }),
@@ -129,5 +144,6 @@ export const useEditorStore = create<EditorState>((set) => ({
railTab: null,
seasonYear: null,
journalObjectId: null,
mode: 'fixtures',
}),
}))