From 78ee892b64a8ce08fa2125a4d25037263db9beb8 Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Wed, 22 Jul 2026 09:49:28 -0400 Subject: [PATCH] Address inspector-peek review: stale docs + selection cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gadfly on #101: - EditorRail's module doc still described a "fixed 20rem column / bottom sheet"; updated to the in-flow peek (desktop column, phone ≤50vh peek between canvas and mode bar). - (correctness) A canvas-mode tap only deselected when railTab was 'inspector', so a selection made, then routed through Journal/Assistant, survived a return to Fixtures/Plants — the canvas kept highlighting it with no inspector. Canvas modes now clear the selection unconditionally. - Dedup: the "closing the inspector deselects" pair lived in both selectMode and the rail's onClose; extracted a clearSelection() helper (also used by exitFocus) and fixed the now-stale "leave an inspector alone" comment. tsc + vitest + build green. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ --- web/src/editor/EditorRail.tsx | 11 ++++++---- web/src/pages/GardenEditorPage.tsx | 32 ++++++++++++++++-------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/web/src/editor/EditorRail.tsx b/web/src/editor/EditorRail.tsx index 15e2106..591a27c 100644 --- a/web/src/editor/EditorRail.tsx +++ b/web/src/editor/EditorRail.tsx @@ -14,11 +14,14 @@ import { cn } from '@/lib/cn' * - Selecting an object must land you in the inspector with no extra click. * The editor watches the selection and switches to that tab itself, so the * rail never becomes a thing you have to operate before you can edit. - * - The canvas has to stay worth watching while the agent edits it, so the - * rail is a fixed 20rem column and closes completely when nothing needs it. + * - The canvas has to stay worth watching while the agent edits it, so the rail + * closes completely when nothing needs it. * - * On a phone the same tabs render in a bottom sheet, which is where the - * inspector already lived. + * Layout differs by breakpoint. Desktop: a fixed 20rem column beside the canvas. + * Phone: an in-flow PEEK (#101) — a ≤50vh panel the editor's flex column places + * BETWEEN the canvas and the always-visible mode bar, so the canvas shrinks to + * keep the garden visible above it and the mode bar reachable below, rather than + * a bottom sheet that covered the whole garden. */ export interface RailTab { diff --git a/web/src/pages/GardenEditorPage.tsx b/web/src/pages/GardenEditorPage.tsx index f6514c6..6d0be53 100644 --- a/web/src/pages/GardenEditorPage.tsx +++ b/web/src/pages/GardenEditorPage.tsx @@ -225,17 +225,25 @@ export function GardenEditorPage() { } }, [selectedId, selectedPlantingId, setRailTab, setMode]) - const exitFocus = () => { - setFocusedObject(null) - setArmedPlant(null) + // Clearing the selection also closes the inspector via the selection effect + // above; shared by exitFocus, the mode bar, and the rail's close so the + // deselect logic lives in one place. + const clearSelection = () => { select(null) selectPlanting(null) } - // The mobile mode bar. Journal/Assistant are panel modes, so they open the - // rail sheet; Fixtures/Plants are canvas modes, so they close a panel rail (but - // leave an inspector, which is about the selection, alone). Tapping Fixtures - // means going back to arranging objects, so it steps out of a focused bed. + const exitFocus = () => { + setFocusedObject(null) + setArmedPlant(null) + clearSelection() + } + + // The mobile mode bar. Journal/Assistant are panel modes, so they open the rail + // as a peek; Fixtures/Plants are canvas modes — a fresh intent — so they close + // whatever's in the rail AND drop any lingering selection (which the canvas + // would otherwise keep highlighted, e.g. after routing a selection through + // Journal and back). Fixtures also steps out of a focused bed. const selectMode = (m: EditorMode) => { setMode(m) if (m === 'journal') { @@ -244,12 +252,7 @@ export function GardenEditorPage() { } else if (m === 'assistant') { setRailTab('chat') } else { - // A canvas mode closes whatever's in the rail; the inspector is about the - // selection, so closing it deselects too. - if (railTab === 'inspector') { - select(null) - selectPlanting(null) - } + clearSelection() setRailTab(null) if (m === 'fixtures' && focusedObjectId != null) exitFocus() } @@ -648,8 +651,7 @@ export function GardenEditorPage() { // deselects; dismissing a panel leaves the canvas as you had it. Any // panel rail (journal/history/chat) drops back to a canvas mode. if (railTab === 'inspector') { - select(null) - selectPlanting(null) + clearSelection() } else { // Back to a canvas mode — Plants if you're still inside a bed, else // Fixtures. (Hardcoding Fixtures here docked the object palette inside