diff --git a/CLAUDE.md b/CLAUDE.md index 6c0fbe8..94f14e9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -615,22 +615,32 @@ layout, since `restore()` is all-or-nothing. ## The Forecast toolbar is two zones -Left, on its own tinted ground: **view** — `Layout ▾` and the `Rows` and -`Columns` depth buttons. Nothing there reaches the server or changes the +Left: **view** — `Layout ▾` and the `Rows` and `Columns` depth steppers, each +with its `Total` toggle. Nothing there reaches the server or changes the forecast; it is all `ViewConfig` against rows already loaded. -Right, in a bordered panel of its own: **forecast** — `Refresh data`, -`Change log`, `Bridge`, `Operations`. These re-run the load, open something over -the pivot, or write to the version. +Right: **forecast** — `Refresh data`, `Change log`, `Bridge`, `Operations`. +These re-run the load, open something over the pivot, or write to the version. + +The distance between them is the separation. Each zone used to be an outlined +box as well, the view one on a `gray-50` tint — too faint to see against white, +and in dark mode the two boxes read as siblings. Within the view zone each axis +is one joined control, `◂ | level | ▸`, in the style of the operation panel's +`Scale | Recode | Clone`, followed by its `Total` chip. + +**Blue is for actions, pressed grey for state.** `Save` and `Post` are blue; +the `Total` chips and `Operations` while its panel is open use `.pf-pressed`. +`Operations` used to relabel itself `Hide panel` in a blue outline, which made +it look like a second Save. They were one undifferentiated row separated by identical hairlines, which made `Fit` and `Bridge` read as peers when one is a column width and the other is the version's history. Three weights do the separating now, and they were all once the same: `.pf-section-label` names a group (`Layout`, `Rows`, `Columns`) and is heavier and darker than the controls under it, `.pf-group-rule` separates groups -*within* a zone, and the zone borders separate the zones. A label that matched -its buttons, and a group rule that matched a zone border, is what made the row -read as one undifferentiated thing. +*within* a zone, and the gap between the zones separates them. A label that +matched its buttons, and a group rule that matched a zone border, is what made +the row read as one undifferentiated thing. **`Fit widths` is gone**, button and `fitColumns` both, for three independent reasons. Auto-size measures the leaf header over the rows *currently in the diff --git a/ui/src/components/DepthButtons.jsx b/ui/src/components/DepthButtons.jsx index b2bdb00..ab3e2f3 100644 --- a/ui/src/components/DepthButtons.jsx +++ b/ui/src/components/DepthButtons.jsx @@ -11,7 +11,7 @@ import { useEffect, useRef, useState } from 'react' // A stepper is three controls whatever the depth, and says where you are rather // than making you find it. The full list is still one click away, for jumping // rather than stepping. -export default function DepthButtons({ label, levels, depth, onPick, totalLabel = 'Total' }) { +export default function DepthButtons({ label, levels, depth, onPick, totalLabel = 'Total', children }) { const [open, setOpen] = useState(false) const boxRef = useRef(null) @@ -36,28 +36,36 @@ export default function DepthButtons({ label, levels, depth, onPick, totalLabel const current = !known ? '—' : (depth === 0 ? totalLabel : levels[depth - 1]) const step = (d) => onPick(Math.min(max, Math.max(0, d))) - const arrow = 'border border-gray-200 rounded px-1 py-0.5 text-gray-500 leading-none ' + - 'hover:border-gray-400 disabled:opacity-30 disabled:hover:border-gray-200 transition-colors' + // One joined control, in the style of the operation panel's + // Scale | Recode | Clone. The arrows used to be separate outlined boxes a + // few pixels wide, which in dark mode were barely visible and looked the + // same enabled or disabled; joined, the axis reads as one object and the + // arrows are halves of it rather than specks beside it. + const seg = 'px-1.5 py-0.5 leading-none bg-white transition-colors ' + + 'text-gray-600 hover:bg-gray-100 disabled:text-gray-300 disabled:hover:bg-white disabled:cursor-default' return ( -
- {label} +
+ {label} - +
+ - + - + +
+ + {children} {open && (
onChange(!on)} + className={`border rounded px-2 py-0.5 transition-colors ${ + on ? 'pf-pressed' : 'border-gray-300 bg-white text-gray-500 hover:bg-gray-100'}`}> + {children} + + ) +} diff --git a/ui/src/components/LayoutMenu.jsx b/ui/src/components/LayoutMenu.jsx index ea310bd..7db8102 100644 --- a/ui/src/components/LayoutMenu.jsx +++ b/ui/src/components/LayoutMenu.jsx @@ -119,7 +119,7 @@ export default function LayoutMenu({ Layout