Editor: the toolkit is a rail tab on desktop, and the rail is wider
Build image / build-and-push (push) Successful in 20s
Gadfly review (reusable) / review (pull_request) Successful in 5m31s
Adversarial Review (Gadfly) / review (pull_request) Successful in 5m31s

The handoff drew the toolkit as a 216px card left of the plan. That width
was better spent on the plan and the rail, so the toolkit is now the rail's
first tab — Toolkit / Plot / Journal / History / Assistant — rendered
`embedded` (no card chrome, no heading; the tab is the heading), the grid
is two columns, and the rail grows from 336 to 400px.

Focusing a bed (double-click) switches the rail to Toolkit, because that is
where the plant palette now lives; a single click still selects into Plot.
The phone chrome is untouched: it never used the card.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-08-23 02:54:45 -04:00
co-authored by Claude Fable 5
parent 0aabccf1bd
commit 10275f5e1c
6 changed files with 47 additions and 26 deletions
+26 -20
View File
@@ -116,6 +116,7 @@ const MODES: { id: PhoneMode; label: string; icon: IconName }[] = [
]
const TABS: { id: RailTab; label: string }[] = [
{ id: 'toolkit', label: 'Toolkit' },
{ id: 'plot', label: 'Plot' },
{ id: 'journal', label: 'Journal' },
{ id: 'history', label: 'History' },
@@ -124,9 +125,11 @@ const TABS: { id: RailTab; label: string }[] = [
/**
* The editor: one canvas, two chromes. Above 760px of container width it is the
* three-card workspace — toolkit, plan, rail; below, a phone layout with the
* canvas as the whole screen, a peek panel that docks between canvas and mode
* bar, and a tool strip for the current mode. Same state, same components.
* two-card workspace — the plan, and a rail whose first tab is the toolkit
* (the handoff drew it as a third card on the left; folding it into the rail
* gave the plan and the rail its width); below, a phone layout with the canvas
* as the whole screen, a peek panel that docks between canvas and mode bar,
* and a tool strip for the current mode. Same state, same components.
*/
function Editor({
gid,
@@ -580,27 +583,29 @@ function Editor({
// ── desktop ─────────────────────────────────────────────────────────────
const tabs = TABS.filter((t) => t.id !== 'chat' || hasAssistant)
const plot = inspector ?? <GardenSummary objects={objects} plantings={plantings} plantsById={plantsById} canEdit={canEdit} />
const toolkit = (
<Toolkit
embedded
unit={unit}
plants={plants}
plantings={plantings}
lotsByPlant={lotsByPlantId}
canEdit={canEdit}
focused={focused}
focusedPlopCount={focusedPlops.length}
canScan={canScan}
filling={fillObject.isPending}
onBack={exitFocus}
onFill={(layout) => focused && armedPlant && fillObject.mutate({ objectId: focused.id, plantId: armedPlant.id, layout })}
onClear={() => setClearing(true)}
onScan={() => setScanning(true)}
/>
)
return (
<div ref={rootRef} className="flex h-dvh flex-col bg-bg">
<Nav active="gardens" />
<div className="grid min-h-0 flex-1 gap-3.5 p-3.5 pt-0 [grid-template-columns:216px_minmax(0,1fr)_336px]">
<Toolkit
unit={unit}
plants={plants}
plantings={plantings}
lotsByPlant={lotsByPlantId}
canEdit={canEdit}
focused={focused}
focusedPlopCount={focusedPlops.length}
canScan={canScan}
filling={fillObject.isPending}
onBack={exitFocus}
onFill={(layout) => focused && armedPlant && fillObject.mutate({ objectId: focused.id, plantId: armedPlant.id, layout })}
onClear={() => setClearing(true)}
onScan={() => setScanning(true)}
/>
<div className="grid min-h-0 flex-1 gap-3.5 p-3.5 pt-0 [grid-template-columns:minmax(0,1fr)_400px]">
<div className="panel flex min-h-0 flex-col overflow-hidden">
<div className="flex flex-wrap items-center gap-3 border-b border-divider px-[18px] py-3">
<h4 className="text-[19px]">{g.name}</h4>
@@ -645,6 +650,7 @@ function Editor({
))}
</div>
<div className="flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-4">
{tab === 'toolkit' && toolkit}
{tab === 'plot' && plot}
{tab === 'journal' && journal}
{tab === 'history' && <HistoryTab canEdit={canEdit} undoLast={undoLast} />}