Touch is a panel setting, and the rail grows with it
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 1m9s
Playwright Tests / test-playwright (2, 2) (push) Failing after 11s
pre-commit / pre-commit (push) Failing after 1m59s
Test Backend / test-backend (push) Failing after 2m28s
Compose Smoke Test / test-compose (push) Failing after 11s
Playwright Tests / merge-reports (push) Failing after 2m19s
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 1m9s
Playwright Tests / test-playwright (2, 2) (push) Failing after 11s
pre-commit / pre-commit (push) Failing after 1m59s
Test Backend / test-backend (push) Failing after 2m28s
Compose Smoke Test / test-compose (push) Failing after 11s
Playwright Tests / merge-reports (push) Failing after 2m19s
It described the wrong object. A dashboard is a document that may hang on a
hallway tablet and in a desk browser at the same time, and only one of those
has fingers on it — so the flag moves off `DashboardDef.settings` and onto
`PanelDef` as a plain bool, ticked in the Panels dialog. `useCanvasRoot` takes
it as an argument rather than reading the document, and `/panel/{id}` is the
only surface with a panel to ask.
Dropping the message binding with it is deliberate: nothing drove it, and a
flow deciding whether a screen has fingers on it was never the point. A stored
`settings.touch` is inert rather than migrated, which `_check_settings`
skipping unknown names already guaranteed.
The rail was the other half. It had no touch behaviour at all and its 40px
buttons met neither branch of the 44/32 rule. `[data-touch] .dui-rail{-item}`
in `ui/core/core.css` spends the padding and the gap on the buttons instead,
so they reach the 44px target and the rail comes out taller at exactly the
same width — `RAIL_INSET` never moves, and the arrangement under it does not
either.
Also closes the panels-dialog icon gap: `DashboardSummary` carries the `icon`
now, so the dialog draws each assigned dashboard's rail glyph beside its
checkbox. `initials()` went from three identical copies in the looks to one in
`Dashboard/icons.ts`, so the dialog and the rail fall back the same way.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Va7ExQDtuwKN7kNpHhWWNQ
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { expect, test } from "@playwright/test"
|
||||
import { expect, type Page, test } from "@playwright/test"
|
||||
import type { PanelDef } from "../src/client"
|
||||
import { api, apiPage, deleteAll } from "./utils/api"
|
||||
|
||||
@@ -35,7 +35,10 @@ test.beforeAll(async ({ browser }) => {
|
||||
{
|
||||
id: "emit",
|
||||
type: "python",
|
||||
provides: [{ name: "level", dtype: "float" }],
|
||||
provides: [
|
||||
{ name: "level", dtype: "float" },
|
||||
{ name: "mode", dtype: "str" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -62,6 +65,23 @@ test.beforeAll(async ({ browser }) => {
|
||||
layout: { lg: { x: 0, y: 0, w: 3, h: 2 } },
|
||||
config: { message: `${flowName}.level`, dtype: "float" },
|
||||
},
|
||||
// Something with a hit target on it, so the touch test can measure a
|
||||
// control rather than only the rail.
|
||||
{
|
||||
id: "mode",
|
||||
type: "dropdown",
|
||||
title: "Mode",
|
||||
layout: { lg: { x: 3, y: 0, w: 4, h: 2 } },
|
||||
config: {
|
||||
target: `${flowName}.mode`,
|
||||
dtype: "str",
|
||||
style: "segmented",
|
||||
options: [
|
||||
{ label: "Eco", value: "eco" },
|
||||
{ label: "Boost", value: "boost" },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
const put = await (
|
||||
await api(page, `/dashboards/${name}`, { method: "PUT", data: doc })
|
||||
@@ -155,6 +175,75 @@ test("the rail is drawn on the panel, in the panel's own look", async ({
|
||||
)
|
||||
})
|
||||
|
||||
test("a touched panel grows its rail without widening it", async ({ page }) => {
|
||||
const open = async () => {
|
||||
await page.goto(`/panel/${flowName}?d=${first}`)
|
||||
await page.getByTestId("panel-rail").waitFor({ timeout: 20000 })
|
||||
}
|
||||
const sizes = async () => ({
|
||||
rail: (await page.getByTestId("panel-rail").boundingBox())!,
|
||||
item: (await page.getByTestId(`panel-rail-${first}`).boundingBox())!,
|
||||
segment: (await page
|
||||
.getByTestId("widget-frame")
|
||||
.filter({ hasText: "Mode" })
|
||||
.getByRole("button")
|
||||
.first()
|
||||
.boundingBox())!,
|
||||
})
|
||||
|
||||
await open()
|
||||
const pointed = await sizes()
|
||||
|
||||
await setTouch(page, true)
|
||||
await open()
|
||||
await expect(page.getByTestId("canvas-surface")).toHaveAttribute(
|
||||
"data-touch",
|
||||
"",
|
||||
)
|
||||
const touched = await sizes()
|
||||
|
||||
// The whole point: the column the rail lives in is reserved by RAIL_INSET
|
||||
// either way, so a wider rail would move the arrangement under it.
|
||||
expect(
|
||||
Math.abs(touched.rail.width - pointed.rail.width),
|
||||
`the rail is ${touched.rail.width.toFixed(1)} touched and ${pointed.rail.width.toFixed(1)} pointed at`,
|
||||
).toBeLessThan(1)
|
||||
expect(touched.rail.height, "the rail did not grow taller").toBeGreaterThan(
|
||||
pointed.rail.height,
|
||||
)
|
||||
expect(
|
||||
touched.item.height,
|
||||
`a rail button is ${touched.item.height.toFixed(1)} touched and ${pointed.item.height.toFixed(1)} pointed at`,
|
||||
).toBeGreaterThan(pointed.item.height)
|
||||
// The widgets are told by the same flag, which used to be the dashboard's.
|
||||
expect(
|
||||
touched.segment.height,
|
||||
"a widget control did not grow with the panel",
|
||||
).toBeGreaterThan(pointed.segment.height)
|
||||
|
||||
// And the arrangement still keeps clear of it.
|
||||
const tile = (await page.getByTestId("widget-frame").first().boundingBox())!
|
||||
expect(
|
||||
tile.x,
|
||||
"a widget is drawn under the touched rail",
|
||||
).toBeGreaterThanOrEqual(touched.rail.x + touched.rail.width)
|
||||
|
||||
await setTouch(page, false)
|
||||
})
|
||||
|
||||
/** What the Panels dialog writes, as the API sees it. */
|
||||
async function setTouch(page: Page, touch: boolean) {
|
||||
const config = await (await api(page, "/panels/")).json()
|
||||
await api(page, "/panels/", {
|
||||
method: "PUT",
|
||||
data: {
|
||||
panels: (config.panels ?? []).map((panel: PanelDef) =>
|
||||
panel.id === flowName ? { ...panel, touch } : panel,
|
||||
),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
test("the rail switches the panel between its dashboards", async ({ page }) => {
|
||||
await page.goto(`/panel/${flowName}?d=${first}`)
|
||||
await page.getByTestId(`panel-rail-${second}`).click()
|
||||
|
||||
Reference in New Issue
Block a user