diff --git a/NOTEPAD.md b/NOTEPAD.md index 502ce83..ec503eb 100644 --- a/NOTEPAD.md +++ b/NOTEPAD.md @@ -35,10 +35,6 @@ Deferring because out of scope is fine, but don't mention deferring than. (`ui/segmented.tsx`, `Common/RangePicker.tsx`, and the flow screens). The dashboard no longer shares them — it has its own, one per look — so unifying the remaining three is now purely an app-side job. -- CHORE/UI: a panel's rail runs the full height of the canvas whatever it - carries, so two dashboards leave most of a tall pill empty. Hugging its - contents and centring would read better; the column it reserves stays the - same either way. - CHORE/UI: the house panels are laid out for 1280x800 — twelve columns, twelve rows. A chart's fixed chrome is now its legend alone: the range picker moved to a column down the right-hand edge and gave its row back, so a third chart diff --git a/frontend/src/components/Dashboard/ui/glass/Surfaces.tsx b/frontend/src/components/Dashboard/ui/glass/Surfaces.tsx index 9dff9ed..910e777 100644 --- a/frontend/src/components/Dashboard/ui/glass/Surfaces.tsx +++ b/frontend/src/components/Dashboard/ui/glass/Surfaces.tsx @@ -158,7 +158,11 @@ export function Rail({ entries }: RailProps) { aria-label="Dashboards on this panel" data-testid={TESTID.rail} className={cn( - "gl-surface gl-rail pointer-events-auto absolute inset-y-3 left-3 z-10 flex w-12 flex-col items-center gap-1 p-1", + "gl-surface gl-rail pointer-events-auto absolute left-3 top-1/2 z-10 flex max-h-[calc(100%-1.5rem)] w-12 -translate-y-1/2 flex-col items-center gap-1 p-1", + // As tall as what it carries, centred in the column it reserves: a + // rail of two stretched to the height of the panel is mostly empty + // pill. More dashboards than the panel is tall still scroll, but no + // bar is ever drawn — a wall panel is swiped, and there is no room. "overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", )} > diff --git a/frontend/src/components/Dashboard/ui/material/Surfaces.tsx b/frontend/src/components/Dashboard/ui/material/Surfaces.tsx index b8a585a..cbe7edd 100644 --- a/frontend/src/components/Dashboard/ui/material/Surfaces.tsx +++ b/frontend/src/components/Dashboard/ui/material/Surfaces.tsx @@ -124,9 +124,11 @@ export function Rail({ entries }: RailProps) { aria-label="Dashboards on this panel" data-testid={TESTID.rail} className={cn( - "m3-rail pointer-events-auto absolute inset-y-3 left-3 z-10 flex w-12 flex-col items-center gap-1 p-1", - // More dashboards than the column is tall still scroll, but no bar is - // ever drawn: a wall panel is swiped, and there is no room for one. + "m3-rail pointer-events-auto absolute left-3 top-1/2 z-10 flex max-h-[calc(100%-1.5rem)] w-12 -translate-y-1/2 flex-col items-center gap-1 p-1", + // As tall as what it carries, centred in the column it reserves: a + // rail of two stretched to the height of the panel is mostly empty + // pill. More dashboards than the panel is tall still scroll, but no + // bar is ever drawn — a wall panel is swiped, and there is no room. "overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", )} > diff --git a/frontend/tests/panel.spec.ts b/frontend/tests/panel.spec.ts index 0f2b228..eaadefd 100644 --- a/frontend/tests/panel.spec.ts +++ b/frontend/tests/panel.spec.ts @@ -8,6 +8,9 @@ import { api, apiPage, deleteAll } from "./utils/api" * is inside the canvas, scaled with it, and wearing the dashboard's own look. * Drawn outside, it was a strip of the app's design bolted to the edge of * somebody's wall panel — and on a scaled canvas it did not even line up. + * + * It is also as tall as what it carries. Stretched end to end, a panel with + * two dashboards showed a pill nine tenths empty. */ const flowName = `test_panel_${Date.now().toString(36)}` @@ -114,6 +117,17 @@ test("the rail is drawn on the panel, in the panel's own look", async ({ ) expect(inside, "the rail is drawn outside the panel it belongs to").toBe(true) + // As tall as what it carries rather than as tall as the panel: a rail of + // two stretched end to end is mostly empty pill. + expect( + box.height, + "the rail is stretched to the height of the panel", + ).toBeLessThan(canvas.height / 2) + const centres = Math.abs( + box.y + box.height / 2 - (canvas.y + canvas.height / 2), + ) + expect(centres, "the rail is not centred in its column").toBeLessThan(2) + // And the arrangement keeps clear of it rather than sitting under it. const tile = (await page.getByTestId("widget-frame").first().boundingBox())! expect(tile.x, "a widget is drawn under the rail").toBeGreaterThanOrEqual(