Repository navigation
Commit 04cbdf7
fix(app-shell): on a read-only item, the Properties panel shown with nothing selected says why its controls are disabled (#29958)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} -->
_Requested by **Yibo Wang** · [project
thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwB4xjiquevJqfBXiUoqfQwa1)_
Fixes #29897
## 维护者速读
-
**改了什么**:元数据编辑页(Studio「所有元数据」条目页)在锁定、只读包等只读状态下,未选中任何元素时显示的「属性」面板,以及无画布页面的通用表单,现在会说明控件为何被禁用:悬停禁用控件或用
Tab 键停到面板时弹出原因提示,读屏器也能读到同一句原因。
-
**为什么改**:选中节点时的检查器早已给出原因,但默认属性面板一直静默置灰,键盘与读屏用户完全得不到原因,违反「禁用控件须说明原因」约定(QA
实测 3/3、2/2 复现)。
- **风险与回滚**:低。只在页面层用已有的 `InspectorReadOnlyReason`
包一层,不改任何注册检查器的契约;可写条目渲染与之前完全一致。回滚即还原 `ResourceEditPage.tsx` 一个文件。
- **先看**:`ResourceEditPage.tsx` 的 `withReadOnlyReason`
及三处包裹点;`ResourceEditPage.inspectorReadOnlyReason-29079.test.tsx` 新增的
objectstack#29897 describe 块。
- **两分钟验证**:在 showcase 中打开
`/_console/studio/~all/metadata/object/showcase_task`,不选中任何字段,悬停「Label」输入框,应弹出以「This
item is locked and cannot be edited or deleted.」开头的原因提示;按 Tab
能停到属性面板并弹出同一句;换一个可写包的条目,面板可编辑且无提示。
- **需要你做的**:无,席位落地。
Clause-②: no
Metadata-protocol: none
## What changes
- **`@object-ui/app-shell`, `ResourceEditPage.tsx`.** The page wraps the
panels it draws itself in `InspectorReadOnlyReason` (the wrapper the
flow node and edge inspectors already use), handing them the same
`inspectorReadOnlyReason` the scoped inspector gets. Three sites: the
registered default inspector shown with nothing selected (object, view,
dashboard, page, report, dataset, action, hook), the generic
`SchemaForm` beside a canvas when the type registers no default
inspector (flow), and the `SchemaForm` of a page with no canvas. The
wrapper draws nothing unless the form is read-only and the reason is
non-blank, so a writable item and view mode render exactly as before.
- **No contract change.** `MetadataDefaultInspectorProps` is untouched
and no registered default inspector was edited: the host draws the
reason around whatever is registered. The scoped-inspector branch is
unchanged (the inspector wraps itself, as since #29203).
- The group's accessible name is the panel's own label
(`engine.edit.inspector.properties`, "Properties"), an existing key in
every locale.
## Tests
New top-level `describe` in the existing page harness
`ResourceEditPage.inspectorReadOnlyReason-29079.test.tsx` (the real
page, the real `ObjectDefaultInspector` and the real `SchemaForm`; only
the canvases and data reads are stubbed):
- Locked object and locked flow, nothing selected: the Properties panel
is a `tabindex=0` group named "Properties" whose accessible description
is the lock sentence plus the served lock reason, and every form control
in it is disabled (or, for the generic form's text inputs, read-only).
- Locked object and locked flow: hovering the first disabled control
opens a tooltip with the reason.
- Locked object and locked flow: tabbing from the top of the page lands
on the panel, which opens the tooltip with the reason.
- CONTROL: a writable object renders the panel live (the Label input
enabled) with no wrapper and no reason.
<details><summary>Ablation (drop the prop)</summary>
`node scripts/ablation-replace.mjs` replaced the wrapper's `
reason={inspectorReadOnlyReason}` with ` reason={undefined /*
ablated-29897 */}` (anchor 1 → 0, blob `a324e465` → `520890e8`), then
ran the file: **6 failed | 7 passed (13)**. The six failures are exactly
the six new locked-item cases; the control and the six existing #29079
cases stayed green. Restored: blob == HEAD (`a324e465`), `git diff HEAD`
empty.
</details>
## Acceptance notes
- The generic form's text inputs (`mdf-name`, `mdf-label` on a flow) are
rendered `readonly`, not `disabled`, so they still take focus on their
own; the reason reaches them through the described panel group around
them. The disabled controls (the flow's Type select, the object panel's
inputs) are the ones the tooltip and the group speak for.
- A page without a canvas in view mode (writable, not editing) still
draws no reason: the page offers an Edit button there and
`inspectorReadOnlyReason` returns none for view mode, as before. The
comment on `inspectorReadOnlyReason` now says so.
- The Source tab (`JsonSourceEditor`) is unchanged; it is out of this
card's scope.
- No README or docs page change: this is an accessibility fix to an
existing panel, not a new feature or prop.
## Verification
All readings at head `d9aae973` on `objectstack-ai/objectstack`, merge
base `21510bba`; heavy runs under `scripts/pm/os-verify-lock.sh` on a
shared box.
<details><summary>Local package checks</summary>
- `pnpm turbo run build --filter='@object-ui/app-shell^...'
--concurrency=2`: 64/64 tasks, exit 0.
- `pnpm --filter @object-ui/app-shell build`: exit 0.
- `pnpm --filter @object-ui/app-shell run type-check` (`tsc --noEmit`
and `tsc -p tsconfig.test.json`): exit 0.
- `pnpm --dir ui exec eslint` on the two touched ui files: 0 errors, 51
warnings, none on a line this PR adds or changes.
- `pnpm --dir ui exec vitest run
packages/app-shell/src/views/metadata-admin/ResourceEditPage.inspectorReadOnlyReason-29079.test.tsx`:
13 passed (13).
- `pnpm --dir ui exec vitest run --maxWorkers=3 packages/app-shell/`:
Test Files 2166 passed, 1 skipped (2167); Tests 19243 passed, 9 skipped;
exit 0.
</details>
<details><summary>Derived gates (dispatch-gates --commands, 35
families)</summary>
`node scripts/pm/dispatch-gates.mjs --ran`: 35 derived, 35 run, 0
NOT-MEASURED, 0 UNRUN, exit 0.
```text
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01WGufziRkHRHwEC3eQwnrwx
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 6e68d8f commit 04cbdf7
3 files changed
Lines changed: 194 additions & 54 deletions
File tree
- .changeset
- ui/packages/app-shell/src/views/metadata-admin
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| 46 | + | |
| 47 | + | |
45 | 48 | | |
46 | 49 | | |
47 | 50 | | |
| |||
68 | 71 | | |
69 | 72 | | |
70 | 73 | | |
| 74 | + | |
71 | 75 | | |
72 | 76 | | |
73 | 77 | | |
| |||
132 | 136 | | |
133 | 137 | | |
134 | 138 | | |
| 139 | + | |
135 | 140 | | |
136 | 141 | | |
137 | 142 | | |
| |||
140 | 145 | | |
141 | 146 | | |
142 | 147 | | |
| 148 | + | |
143 | 149 | | |
144 | 150 | | |
145 | 151 | | |
| |||
148 | 154 | | |
149 | 155 | | |
150 | 156 | | |
| 157 | + | |
151 | 158 | | |
152 | 159 | | |
153 | 160 | | |
| |||
241 | 248 | | |
242 | 249 | | |
243 | 250 | | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
146 | 146 | | |
147 | 147 | | |
148 | 148 | | |
| 149 | + | |
149 | 150 | | |
150 | 151 | | |
151 | 152 | | |
| |||
2621 | 2622 | | |
2622 | 2623 | | |
2623 | 2624 | | |
2624 | | - | |
| 2625 | + | |
| 2626 | + | |
2625 | 2627 | | |
2626 | 2628 | | |
2627 | 2629 | | |
| |||
2638 | 2640 | | |
2639 | 2641 | | |
2640 | 2642 | | |
| 2643 | + | |
| 2644 | + | |
| 2645 | + | |
| 2646 | + | |
| 2647 | + | |
| 2648 | + | |
| 2649 | + | |
| 2650 | + | |
| 2651 | + | |
| 2652 | + | |
| 2653 | + | |
| 2654 | + | |
| 2655 | + | |
| 2656 | + | |
| 2657 | + | |
2641 | 2658 | | |
2642 | 2659 | | |
2643 | 2660 | | |
| |||
3562 | 3579 | | |
3563 | 3580 | | |
3564 | 3581 | | |
3565 | | - | |
3566 | | - | |
3567 | | - | |
3568 | | - | |
3569 | | - | |
3570 | | - | |
3571 | | - | |
3572 | | - | |
3573 | | - | |
3574 | | - | |
3575 | | - | |
3576 | | - | |
3577 | | - | |
3578 | | - | |
3579 | | - | |
3580 | | - | |
3581 | | - | |
3582 | | - | |
3583 | | - | |
| 3582 | + | |
| 3583 | + | |
| 3584 | + | |
| 3585 | + | |
| 3586 | + | |
| 3587 | + | |
| 3588 | + | |
| 3589 | + | |
| 3590 | + | |
| 3591 | + | |
| 3592 | + | |
| 3593 | + | |
| 3594 | + | |
| 3595 | + | |
| 3596 | + | |
| 3597 | + | |
| 3598 | + | |
| 3599 | + | |
| 3600 | + | |
| 3601 | + | |
| 3602 | + | |
3584 | 3603 | | |
3585 | | - | |
3586 | | - | |
3587 | | - | |
3588 | | - | |
3589 | | - | |
3590 | | - | |
3591 | | - | |
3592 | | - | |
3593 | | - | |
3594 | | - | |
3595 | | - | |
3596 | | - | |
3597 | | - | |
3598 | | - | |
3599 | | - | |
3600 | | - | |
3601 | | - | |
| 3604 | + | |
| 3605 | + | |
| 3606 | + | |
| 3607 | + | |
| 3608 | + | |
| 3609 | + | |
| 3610 | + | |
| 3611 | + | |
| 3612 | + | |
| 3613 | + | |
| 3614 | + | |
| 3615 | + | |
| 3616 | + | |
| 3617 | + | |
| 3618 | + | |
| 3619 | + | |
| 3620 | + | |
| 3621 | + | |
| 3622 | + | |
3602 | 3623 | | |
3603 | 3624 | | |
3604 | 3625 | | |
| |||
3610 | 3631 | | |
3611 | 3632 | | |
3612 | 3633 | | |
3613 | | - | |
3614 | | - | |
3615 | | - | |
3616 | | - | |
3617 | | - | |
3618 | | - | |
3619 | | - | |
3620 | | - | |
3621 | | - | |
3622 | | - | |
3623 | | - | |
3624 | | - | |
3625 | | - | |
3626 | | - | |
3627 | | - | |
3628 | | - | |
3629 | | - | |
| 3634 | + | |
| 3635 | + | |
| 3636 | + | |
| 3637 | + | |
| 3638 | + | |
| 3639 | + | |
| 3640 | + | |
| 3641 | + | |
| 3642 | + | |
| 3643 | + | |
| 3644 | + | |
| 3645 | + | |
| 3646 | + | |
| 3647 | + | |
| 3648 | + | |
| 3649 | + | |
| 3650 | + | |
| 3651 | + | |
| 3652 | + | |
3630 | 3653 | | |
3631 | 3654 | | |
3632 | 3655 | | |
| |||
0 commit comments