Skip to content

fix(console): dashboards meet the 44 px touch-target floor at phone width - #29149

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g98ica
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-g98ica

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #29078

Part of #29040 (the Dashboards flow; the other seven flows have their own cards).

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:手机宽度(小于 sm,即 640 px)下,仪表盘页面的可点控件统一放大到 44 px 触控目标:页头「Refresh All」、筛选栏的日期/下拉/文本控件与「Reset」、下拉选项行、自定义日期日历(手机上只显示一个月,日期格 44 px)、数据表的排序按钮与可钻取行、透视表的可钻取单元格、「Export CSV」(手机上移到表格上方单独一行,不再压住最后一列的排序按钮)、钻取抽屉的「Open in list」,以及所有 Sheet 抽屉的关闭按钮。桌面宽度(sm 及以上)样式不变。
  • 为什么改:Console at phone width: audit and fix the key flows at 375px (the mobile app now hosts the Console) #29040 要求移动端(WebView 内嵌 Console)逐流程审计。在真实 Console 上以 375 与 390 px 跑 CRM 和 showcase 的 4 个仪表盘:无横向滚动、弹层全部在视口内、4 倍 CPU 降速下滚动顺畅,唯独触控目标不达标,控件高 16 到 36 px。
  • 风险与回滚:只改 className,不动属性、数据或协议;唯一共享组件改动是 sheet.tsx 的关闭按钮,只加 max-sm: 前缀类,桌面不变,手机上所有抽屉的关闭按钮变成 44 px;该文件由 shadcn 同步生成,改动已登记为本地补丁,同步时自动重放。回滚即还原本 PR。
  • 先看:ui/packages/components/src/ui/sheet.tsx 与 ui/scripts/shadcn-local-patches.mjs(全局抽屉关闭按钮,作为 shadcn 本地补丁声明)、ui/packages/plugin-dashboard/src/DatasetWidget.tsx(Export CSV 手机上改为独立一行)、ui/packages/plugin-dashboard/src/DashboardFilterBar.tsx(日历手机上单月)。
  • 两分钟验证:cd ui && pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardPhoneTouchTargets-29078.test.tsx packages/components/src/__tests__/sheet-close-touch-target-29078.test.tsx packages/app-shell/src/views/DashboardView.phoneTouchTarget-29078.test.tsx,预期 3 个文件 10 个用例全绿。
  • 需要你做的:无,席位落地。

What changes

Every change is phone-only: a class under max-sm:, or a min-h-11 floor released by sm:min-h-0 (the pattern the form select trigger already uses). From sm up the class lists draw what they drew before.

  • @object-ui/app-shell, DashboardView.tsx: the page header's Refresh All gets the 44 px floor.
  • @object-ui/plugin-dashboard, DashboardFilterBar.tsx: the date-range and select triggers, the text filter, Reset, and every option row of both lists get the floor. The custom-range calendar opens one month below md (useIsMobile) with 44 px day cells (max-md:[--cell-size:2.75rem]); two stacked months at that size would run past a phone's viewport. From md up it keeps two months at 32 px.
  • @object-ui/plugin-dashboard, DatasetWidget.tsx: the table's sort buttons get the floor; the cells of a drillable row are 44 px tall (a table nobody can drill is unchanged); a drillable pivot cell is 44 by 44. Export CSV is 44 px and, below sm, leaves the table's top-right corner (where it would cover the last column's sort button) for its own right-aligned row above the table.
  • @object-ui/plugin-dashboard, OpenInListButton.tsx: the drill drawer's Open in list gets the floor; a host className still merges.
  • @object-ui/components, sheet.tsx: the Close button every Sheet draws is a 44 px box below sm, its 16 px glyph where it was. The Dialog close button is not touched.
  • ui/scripts/shadcn-local-patches.mjs: src/ui/** regenerates from the shadcn registry, so the Sheet edit is declared as the local patch sheet-close-phone-touch-target (one anchor, written from the vendored sheet.registry.txt bytes) and re-applied by the sync. Without it the next shadcn:update would revert it silently; shadcn-local-patches.test.ts caught the undeclared edit.

Why

The card asks for the Dashboards flow driven at 375×812 and 390×844 against the showcase and CRM examples, five checks each. The audit ran first on origin/main 6b3ba82c, on a real Console, and only the touch-target check failed. Claim 6571438083 declared the audit read-only; the seat then amended the surface to these five files, their tests and a changeset (amendment 6571555427) before any push, and added ui/scripts/shadcn-local-patches.mjs and its tests (amendment 6572329768) once the derived gates showed the Sheet edit had to be declared there.

Run record

Harness: pnpm build + pnpm console:build, the Console served at /_console by pnpm dev:crm -- --fresh and pnpm dev:showcase -- --fresh, Playwright Chromium with isMobile, hasTouch, an Android UA and DPR 2. Pages: CRM pipeline_dashboard (KPIs, line, bar, pie); showcase showcase_ops_dashboard (date and select filters, KPIs, charts, table), showcase_revenue_pulse (date and region filters, KPIs, charts, table), showcase_chart_gallery (every chart type, table, pivot). Before and after screenshots and the raw reports stay in the project folder.

Check 375×812 before 375×812 after 390×844 before 390×844 after Evidence
No horizontal page scroll PASS PASS PASS PASS page overflow 0 on all 4 dashboards, no element past the right edge. Tables and the pivot scroll sideways inside their own card, not the page.
Touch targets ≥ 44 px FAIL PASS FAIL PASS before: Refresh All 36, filter triggers 32, option rows 32, calendar days and arrows 32, sort buttons 16, drillable rows 25, pivot cells 25, Export CSV 22, drawer Close 16, Open in list 36. After: 0 targets under 44 in the page, the filter lists, the calendar and the drill drawer.
Dialogs and drawers fit PASS PASS PASS PASS filter lists inside the viewport (after: B802 of 812, B834 of 844); custom range before two stacked months to B709, after one month T147 to B512; drill drawer full screen. No overlay overflows sideways.
Virtual keyboard does not cover the focused field N/A N/A N/A N/A no text-entry field in the flow: the four dashboards declare only date and select filters, the custom range is a calendar, the drill drawer has no input.
Long lists responsive at CPU 4× PASS PASS PASS PASS CDP setCPUThrottlingRate 4: the dashboard scroller (up to 6.5k px) scrolled in 30 steps with p95 frame 17 ms and 0 long tasks; tap on a table row to drill drawer visible 507 to 749 ms, the data request included.

Not fixed here, and not this card's file surface: the Console app bar's controls (sidebar toggle 28 px; home, search, Studio, inbox, account 32 px) are under 44 px on every route. They are AppHeader's, held by the Navigation card #29075.

Tests

  • New ui/packages/plugin-dashboard/src/__tests__/DashboardPhoneTouchTargets-29078.test.tsx (8 cases): filter triggers, text field and Reset carry the floor; every option row of both lists does; below md the custom range opens one month with the 44 px cell size, and from md up it keeps two (control); sort buttons and drillable-row cells carry the floor and Export CSV is 44 px out of the corner; a non-drillable table's rows do not grow (control); a drillable pivot cell is 44 by 44; Open in list carries the floor and keeps a host class.
  • New ui/packages/app-shell/src/views/DashboardView.phoneTouchTarget-29078.test.tsx (1 case): Refresh All carries the floor.
  • New ui/packages/components/src/__tests__/sheet-close-touch-target-29078.test.tsx (1 case): the Sheet Close button is 44 px below sm, keeps right-4 top-4 from sm up and its 16 px glyph.
  • Reverse verification: with the five source files checked out from origin/main 6b3ba82c, the three files ran 8 failed, 2 passed (the two controls), then restored from HEAD (git diff HEAD empty). These tests import the components from source, so no build stands between the edit and the run.
  • ui/scripts/__tests__/shadcn-local-patches.test.ts was red on 0ff4d360 (1 case, "sheet: byte round-trip holds": sheet.tsx no longer regenerated from registry bytes) and is green on 8423b760 with the patch declared.
  • On 0ff4d360: the whole packages/plugin-dashboard/ suite, 200 files, 1922 passed, 6 skipped; the 43 components, app-shell and console test files naming sheet or the touched dashboard modules, 404 passed; turbo run type-check for components, plugin-dashboard and app-shell, 67 of 67 tasks.

Acceptance notes

  • Chart segments are drill targets sized by the data (bars 39 to 56 px wide, some gallery bars 30 px tall). They are not controls this PR resizes.
  • The drill drawer lists held 2 to 4 seed rows, so a long drawer list was not exercised at 4× CPU; the dashboard scroller itself (6.5k px) was.
  • No Playwright spec is added; the card welcomes one where a fix lands but does not require it for this flow. The audit harness and its reports are in the project folder.

Verification

Derived gates, local subset

node scripts/pm/dispatch-gates.mjs --commands derived 36 families. On 0ff4d360 all 36 ran: 35 exit 0 (among them check-sdui-manifest.mjs and its self-test, check-changeset-no-major, check-empty-changeset, check-adr-0087-registration, check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias, check:query-options-erasure, and check:type-check-debt under the verify lock), and pnpm --dir ui exec vitest run scripts/ exit 1 on the one shadcn round-trip case above. dispatch-gates --ran: 36 derived, 36 run, 0 NOT-MEASURED. On 8423b760 the same derivation (identical list): pnpm --dir ui exec vitest run scripts/ exit 0, 169 files passed, 2 skipped (4900 tests). The other 35 are re-running on 8423b760; their results go in the os-dev report on the card.

Families CI runs (Lint UI, Test UI, Type Check UI and the rest) are read from this PR's check-runs.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (Not touched.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (No formatter ran; pnpm lint is CI's Lint UI run.)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English, except the 维护者速读 block the lane requires.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QsR2jTE9T9iArKPf81eTtb

…idth

Below sm, the dashboard page's Refresh All, the filter bar's triggers,
option rows and custom-range calendar (one month, 44 px days), the dataset
table's sort buttons, drillable rows and pivot cells, its Export CSV
button, the drill drawer's Open in list and every Sheet's Close button
are 44 px touch targets. Desktop sizes are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTE9T9iArKPf81eTtb
…n local patch

ui/packages/components/src/ui/** regenerates from the shadcn registry, so
the phone class list on the Sheet close button is declared in
shadcn-local-patches.mjs (anchored on the registry bytes) and re-applied
by the sync; the inline JSX comment moves into the declaration.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTE9T9iArKPf81eTtb
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

席位核对 · ACCEPT · 2026-11-02T09:01Z

Head-sha: 8423b76039e1fb211ee880e8201ef9010df12f7d

  • Shape:
    • The PR is a draft against main. The first card line is Fixes #29078, and Console at phone width: audit and fix the key flows at 375px (the mobile app now hosts the Console) #29040 is cited as Part of.
    • 10 files, +420 / −18, inside the surface set by amendments 6571555427 and 6572329768: DashboardView.tsx, DashboardFilterBar.tsx, DatasetWidget.tsx, OpenInListButton.tsx, sheet.tsx (its Close only), ui/scripts/shadcn-local-patches.mjs, three new tests and a root changeset. check-governed-merges --pr 29149: 438 changed lines, under the human-merge threshold.
    • Clause-②: no and Metadata-protocol: none start their lines in the body and the changeset, as claimed: className changes and a declared local patch only. The changeset is patch.
  • Read in the diff:
    • Every size change is phone-only (max-sm: or min-h-11 sm:min-h-0), so desktop is unchanged.
    • The Sheet Close fix is declared as sheet-close-phone-touch-target in shadcn-local-patches.mjs, anchored on the vendored sheet.registry.txt line, with a marker. sheet.tsx is byte-for-byte registry plus declared patches, so the sheet: byte round-trip holds case passes and pnpm shadcn:update keeps the fix.
  • Gates (check-runs on this head): 44 success, 11 skipped, 0 failed or pending. mergeable_state is clean.
  • Tests (dev): 3 new files with 10 cases; 8 of 10 red on main's sources (2 controls green). plugin-dashboard 200 files; 43 neighbour files 404; type-check 67 of 67; ui scripts/ 169 green on this head. Derived gates 36 of 36. The after-audit passes at 375 and 390 px on CRM pipeline and three showcase dashboards.
  • NOT MEASURED: the seat ran no live session.
  • Serial: Dialog close button at phone width: the X in the shared Dialog is a 16x16 px target, below the 44 px minimum, in every modal the mobile app shows #29107 (seat 2, dialog.tsx) adds a dialog entry to shadcn-local-patches.mjs and merges main after this lands. report table: a dataset dimension nullLabel is not drawn — the null bucket reads "—" although the dataset query answer carries the label #29010 (seat 2, DatasetWidget.tsx) is unblocked once this lands.
  • Landing: ordinary queue landing, pr_ready then automerge_enable. Fixes #29078 closes the card on merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Console at phone width: Dashboards flow audit and fixes at 375 and 390 px

1 participant