Skip to content

fix(app-shell): read-only flow node inspector gives its reason on hover, focus and to assistive tech - #29073

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

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-b1swwl

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #28985

Clause-②: yes (widening)
Metadata-protocol: none

维护者速读

  • 改了什么:Studio 流程画布上,只读包的节点属性栏现在会说明控件为什么是灰的:鼠标悬停任一灰色控件弹出原因提示,键盘 Tab 能停在属性栏上并读出原因,读屏把原因当作描述读出。做法与字段栏、校验规则编辑器一致。原因文字由宿主传入(新增可选属性 readOnlyReason),Studio 自动化页传「只读软件包」那句。
  • 为什么改:打开已安装包(如 showcase)的流程,点中节点后整栏灰掉,悬停、Tab、读屏都得不到原因;平台测试清单 ux-conventions.disabled-control-reason 因此判失败。
  • 风险与回滚:低。只在「只读且宿主给了原因」时多包一层可聚焦的分组;不传原因的宿主(如元数据管理页)渲染与之前完全一样。可写时不变。回滚即还原本 PR。
  • 先看:FlowNodeInspector.tsx 末尾新增的只读原因分组;inspector-registry.ts 的 readOnlyReason;StudioDesignSurface.tsx 流程宿主调用处新增的一行。
  • 两分钟验证:在 ui/ 下运行 pnpm exec vitest run packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.readOnlyReason-28985.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.automationsReadOnly-11124.test.tsx,预期 2 个文件、16 个测试全绿。
  • 需要你做的:无,席位落地。

What changes

  • MetadataInspectorProps.readOnlyReason?: string (inspector-registry.ts, exported from the @object-ui/app-shell entry). The inspector is shared by hosts whose read-only causes differ: Studio's Automations pillar is read-only because the package is, while the metadata editor page is also read-only in view mode or on a walled item. So the host says why, and an inspector that honours the prop draws it while readOnly is true. Optional, so every existing host and inspector compiles and renders unchanged.
  • FlowNodeInspector wraps its panel, when readOnly and the reason is non-blank, in the treatment Studio's field rail and validation-rule editor carry: a role="group" named by the node, tabIndex={0}, aria-describedby an sr-only copy of the reason, and the trigger of a tooltip that shows it. One trigger for the panel, not one per control, because the reason is the same for all of them. The wrapper is inline, as in those two surfaces: no exported wrapper exists to reuse (the two are inline JSX and DisabledReasonTrigger is private to @object-ui/components).
  • Studio's Automations pillar passes engine.studio.pkg.readonlyHint as readOnlyReason when editLocked, one prop at the flow inspector's call site in StudioDesignSurface.tsx.

Tests

  • New: FlowNodeInspector.readOnlyReason-28985.test.tsx, 6 cases on an update_record node:
    • read-only with a reason: the panel is a tab stop, named by the node, described by the reason, and holds every disabled control (ID, Label, Node Type, the config fields, Remove node; at least four, so a vacuous pass is not one);
    • hovering the disabled Remove node opens a tooltip with the reason;
    • Tab lands on the described panel and opens the tooltip;
    • controls: read-only with no reason renders no tab stop or description; a blank reason counts as none; a writable inspector ignores a reason and its controls are live.
  • Changed: StudioDesignSurface.automationsReadOnly-11124.test.tsx. The read-only case now asserts the opened node inspector sits inside the described group with the package's reason, through the real pillar, FlowPreview and FlowInspector; the writable control asserts no group.
  • Red on main. With FlowNodeInspector.tsx and StudioDesignSurface.tsx restored from ab085a04, the two files ran 4 failed and 12 passed: the three new reason cases and the host case fail, every control passes. With the fix, 16 of 16 pass.

Acceptance notes

  • The tooltip also opens when hovering the header's close button in the stand-alone shell (outside Studio), since the whole panel is the trigger; the field rail behaves the same way.
  • The metadata editor page (ResourceEditPage) passes no reason yet, so its read-only node inspector is unchanged; its causes (no write access, a walled item, view mode) each need their own sentence, which is out of this card's scope and reported to the seat.
  • FlowEdgeInspector (a selected connection) disables its controls on readOnly the same way and is not covered by this card; reported to the seat. It now receives the reason through the same props and ignores it.

Verification

All readings on head 447e0f65 unless named (fix 608e38ed, node-name follow-up 447e0f65), base ab085a04.

Tests
  • pnpm exec vitest run (from ui/) on the two pinned files plus flowNodeLabels.sites-13200.test.ts: 3 files, 51 tests passed.
  • Red on main: the two pinned files with FlowNodeInspector.tsx and StudioDesignSurface.tsx restored from ab085a04: 4 failed, 12 passed (the three reason cases and the host case). Restored with git checkout HEAD, git diff HEAD empty.
  • Sweep of the 116 ui test files that git grep finds naming FlowNodeInspector, FlowInspector, AutomationsPillar or MetadataInspectorProps, in three locked batches at --maxWorkers=2: 38/38 files (415 tests), 38/38 (474), 40/40 (330). The first run of the middle batch caught flowNodeLabels.sites-13200.test.ts (an id-shaped node name in the group's aria-label); 447e0f65 names it through flowNodeDisplayName, and that batch re-ran green on the final head. Narrowed on purpose: CI's Test UI runs the rest of app-shell.
  • pnpm exec turbo run type-check --filter=@object-ui/app-shell: 65 of 65 tasks successful.
  • eslint on the four changed ui files other than StudioDesignSurface.tsx: 0 errors (3 existing warnings in FlowNodeInspector.tsx, untouched lines).
Gates
  • node scripts/pm/dispatch-gates.mjs --commands derived 34 families; all 34 ran with exit 0, the 33 unlocked ones with this body as the PR event (check-adr-0087-registration, check-changeset-no-major, check-closing-keyword-parity, check-sdui-manifest among them), and pnpm --dir ui exec vitest run scripts/ locked: 169 files passed, 2 skipped (4,900 tests).
  • dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN.
  • check:new-line-citations: 0 new citations.

Generated by Claude Code

…er, focus and to assistive tech

MetadataInspectorProps gains an optional readOnlyReason the host fills in;
FlowNodeInspector draws the focusable, aria-describedby reason group around
its panel while read-only, and Studio's Automations pillar passes the
read-only package sentence.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTpDoNt6xHzNNCFygz
… display rule

The node-name guard holds every id-shaped site in the flow designer; the
group's accessible name now reads flowNodeDisplayName like the rest.

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

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

席位核对 · ACCEPT · 2026-11-02T07:09Z

Head-sha: 447e0f650219be8647b8e70c240124dae949396e

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 Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio flow node inspector: on a read-only package every control is disabled with no reason on hover, keyboard focus or to assistive tech

1 participant