Repository navigation
fix(plugin-dashboard): a layout-less metric tile spans one row, and a geometry pin holds one-row tiles at content height (objectui#12704) - #12857
Conversation
… geometry pin holds one-row tiles at content height (objectui#12704) On a dashboard that declares `columns`, a metric widget with no `layout` now spans one grid row instead of two, the height the designer gives a new widget. The row floors at 5rem and grows to the tile's content, so the second row was the tile's empty lower half. Non-metric widgets keep four rows; an authored `layout.h` is unchanged. e2e/dashboard-metric-tile-height.spec.ts bundles the real DashboardRenderer from source, mounts it in Chromium with a stub `queryDataset`, and measures a bare one-row tile, a one-row tile with a delta line and a two-row CONTROL at 1280 and 1024 px. Claude-Session: https://claude.ai/code/session_01BxWPtU5qnbTX3RoZJqNSza Co-authored-by: Claude <noreply@anthropic.com>
… keep its readings and picture (objectui#12704) - Compile the Tailwind sheet until the page's class set stops growing: a one-shot sheet sometimes missed a class added by a later render (the card's `border`), moving the reading by 2 px between runs. - Import the i18n provider by source path, so the spec names no workspace package in an import statement (the e2e type-check premise). - Record the readings as a test annotation (no console statement) and attach a full-page screenshot under test-results. Claude-Session: https://claude.ai/code/session_01BxWPtU5qnbTX3RoZJqNSza Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
席位核对 — ACCEPT · objectui#12704 · head
|
| case | 1280 px | 1024 px |
|---|---|---|
h: 1, bare value |
124.38 | 124.38 |
h: 1, with a delta line |
146.38 | 146.38 |
h: 2 CONTROL |
176 (2 × 80 + 16) | 176 |
| bare and delta in one row | both 146.38 | both 146.38 |
The 1280 readings equal the earlier live console measurement on the HotCRM scratch dashboard (124.38 / 146.38 / 176). The pin asserts relations, not pixels:
- a one-row box ends 25 px (its padding and border) below its last line;
- the delta tile is taller than the bare one;
- the
h: 2tile is two rows plus the gap; - tiles in one row align on the tallest.
Screenshots, read by the seat (never-merged claude/issue-12704-evidence-2 at e1483b8), 1280 px and 1024 px light. They show:
- the bare tile hugging its three lines;
- the delta tile one line taller;
- the
h: 2CONTROL with its empty lower half; - the bare-and-delta pair aligned in one row.
Sent to the maintainer at 2026-10-17T04:34Z.
Tests:
- The unit pin
DashboardRenderer.metricFallbackSpan-12704.test.tsx: a layout-less metric spansspan 3/span 1. Two CONTROLs: an authoredh: 2keepsspan 2, and a layout-less table keepsspan 6/span 4. - Three ablations went red, each through
ablation-replaceand each restored to an emptygit diff HEAD:- the bare case forced to
h: 2; - the row floor raised to
12rem: "the one-row box runs 67.63px past its content and padding"; - the default reverted to
h: 2: the unit pin goes red, and its CONTROLs stay green.
- the bare case forced to
@object-ui/plugin-dashboardin full: 183 files, 1814 tests passed.type-check,lintandbuildfor the package,type-check:e2eand the e2e type-check test: all exit 0.
Changeset: @object-ui/plugin-dashboard patch; user-facing prose.
CI: running at this record. The dev ran the geometry spec with a scratch config, because the container's Chromium revision differs from Playwright's. Build & E2E on this PR is the first run with the literal spelling, and landing waits for it to go green.
Rulings
- The fixture mounts on the client: A, as built. It measures the tile a metadata dashboard reaches, through the real loading effect, and adds no test-only seam to the renderer. B would need product code written for the test.
- The metadata halves: platform-objects: System Overview's six metric tiles declare
layout.h: 2and draw a half-empty box; set them toh: 1(ruling B on objectui#12704) objectstack#24126 (System Overview) and dashboards: everyh: 2metric tile draws a half-empty box at 1024 px; set them toh: 1, keep the two deliberateh: 4(ruling B on objectui#12704) hotcrm#2135 (Sales Performance) are open. Their screenshot acceptance stays theirs, as ruled. This PR closes the renderer's half: the default and the pin. defaultWidgetPlacement(edit mode gives a layout-less widgeth: 4): noted, not filed. The read and edit grids disagreed before this PR (2 against 4) and still do (1 against 4). The function is outside this card's surface.- The contract conflict: as dispatched. The relay is refused from the dev's container, so the seat opened the PR and relayed the report.
Implemented-by: cloud session session_01BxWPtU5qnbTX3RoZJqNSza, branch claude/issue-12704-metric-tile-height-pin
Generated by Claude Code
Landing · head
|
Fixes #12704
Clause-②: no
What changed
packages/plugin-dashboard/src/DashboardRenderer.tsx,fallbackSpaninrenderWidget): on a dashboard that declarescolumns, a metric widget with nolayoutnow spansh: 1instead ofh: 2. That is the heightDashboardEditor'saddWidgetgives a new widget. Non-metric widgets keeph: 4. An authoredlayout.his unchanged.e2e/dashboard-metric-tile-height.spec.ts, besidee2e/sidebar-offcanvas-geometry.spec.ts. It bundles the realDashboardRendererand its imports from source with Vite (each@object-ui/*resolved to itssrc/, built in memory). It mounts the bundle in Chromium with React's client renderer, so the dataset tile goes through its real loading effect. The data source is a stubqueryDataset(thedataSourceprop the renderer takes). No server runs. The stylesheet is the real theme sheet,packages/components/src/index.css, compiled with Tailwind for the classes on the page.packages/plugin-dashboard/src/__tests__/DashboardRenderer.metricFallbackSpan-12704.test.tsx: a layout-less metric spansspan 3/span 1. Two CONTROLs: an authoredlayout.h: 2keepsspan 2, and a layout-less table keepsspan 6/span 4.patchchangeset for@object-ui/plugin-dashboard.minmax(5rem, auto),span h),MetricCard.tsx, the tile padding and chrome,DashboardEditor.tsx. Nopackages/specchange.Why the pin is a Playwright spec
The claims are heights the grid computes. jsdom has no layout engine, so the
__tests__shape could only pin the span, and it does that for the default. Its stub is a JavaScript object, not a server, so the ruling's fallback (letter D) does not apply.Measured heights (Chromium, light, 12 columns, quarter-width tile)
h: 1, bare value (title, value, measure label)h: 1, with a delta lineh: 2CONTROLThe 1280 readings equal the earlier live console measurement on the HotCRM scratch dashboard (124.38 / 146.38 / 176). At 1024 the fixture has no sidebar, so the tile stays wider than 160 px and its measure label shows. In the console with the sidebar, the tile was narrower and measured 117.75 px. The pin asserts relations, not pixel equality across fonts:
h: 2tile is two rows plus the gap, with more than 40 px of empty lower half;Screenshots, evidence branch only (never merged):
The two metadata cards
Neither has landed. On objectstack
main9ffe8afSystem Overview's 6 metric tiles are stillh: 2(objectstack-ai/objectstack#24126). On hotcrmmain4f82b81Sales Performance's KPI tiles are stillh: 2(objectstack-ai/hotcrm#2135). The screenshot acceptance of Sales Performance and System Overview waits for them, as ruled.Test evidence (HEAD
a20446a)CI=1 playwright testwith the repo'splaywright.config.ts, projectchromium, one2e/dashboard-metric-tile-height.spec.tsande2e/sidebar-offcanvas-geometry.spec.ts: 8 expected, 0 unexpected, 0 flaky. Local differences from CI: a launchexecutablePathfor the preinstalled Chromium, and no console preview server (neither spec uses it). Stable over--repeat-each=4.ablation-replacewith on-disk proof and a restore togit diff HEADempty:h: 2: red (span check);minmax(5rem, auto)changed tominmax(12rem, auto), span unchanged: red, "bare: the one-row box runs 67.63px past its content and padding";h: 2: the unit pin goes red (expectedspan 1, receivedspan 2) and both CONTROLs stay green.pnpm --filter @object-ui/plugin-dashboard test: exit 0, 183 files passed, 1814 tests passed, 6 skipped (run onb6dfaf0; no plugin-dashboard file changed after it).type-check,lint,buildfor@object-ui/plugin-dashboard: exit 0 each (lint warnings only, none on changed lines).pnpm type-check:e2eexit 0.scripts/__tests__/e2e-type-check.test.ts15/15. ESLint on the touched files exit 0.node scripts/check-changeset-presence.mjsexit 0.pnpm check:new-line-citationsreports 0 new.Acceptance notes
defaultWidgetPlacementinpackages/typesstill gives every layout-less widgeth: 4in the editable grid (DashboardGridLayout, theDashboardWithConfigsliders), metrics included. The read grid now says 1 row for a layout-less metric, while edit mode says 4. That function is outside this card's claimed files, so it is untouched here. Not reproduced live.Session:
https://claude.ai/code/session_01BxWPtU5qnbTX3RoZJqNSzaGenerated by Claude Code