fix(app-shell,components,plugin-detail): 对象表单之外五处渲染器把必填状态送进 a11y 树 (#3299) - #3340
Merged
Merged
Conversation
… five renderer sites outside the object form (#3299) Five renderers computed `required`, painted a red asterisk, and put NO required state on the control — the same defect #3290/#3298 fixed in form.tsx, at the five sites its scope fence excluded. Four of them were worse than pre-fix form.tsx: the bare `*` had no `aria-hidden`, so the only "signal" was a literal asterisk folded into the accessible name ("Title asterisk"). Every site converges on the reference shape (EmbeddableForm.tsx:481,489): - control: `aria-required={required || undefined}` — absence, not "false", for optional fields; - asterisk: `aria-hidden="true"` — announced once, as a state, never as part of the name. Sites: - app-shell/ActionParamDialog: both branches (boolean row + default); the state rides the widget props and reaches the DOM through the fields' `toDomProps` whitelist, which forwards `aria-*` by prefix. - app-shell/CreateViewDialog: display label, machine name, and each type-specific required-field selector (statically required, so a literal `aria-required="true"`). - components/custom/action-param-dialog: all five typed branches; for select the state lands on the Radix trigger (the focusable combobox — the root renders no element). - components/custom/field: FieldContainer injects `aria-required` via the same Slot that already injects id/aria-describedby/aria-invalid — one line covers every consumer. Its asterisk is a CSS pseudo-element, which never enters the a11y tree, so no marker change is needed there. - plugin-detail/InlineCreateRelated: create-tab inputs. Deliberately NOT native `required` (#3290 ruling): each host runs its own validation; native required would arm the browser's constraint- validation bubble beside it. The SDUI controls that already set native `required` (renderers/form/{input,textarea,select,checkbox}.tsx, basic/text-input.tsx) are excluded per the issue — no second validator there, so their channel is already correct. Tests per site, with mutation verification on the two load-bearing deliveries (FieldContainer's Slot injection; the app-shell dialog's widget-chain delivery): attribute removed -> red, restored -> green. Fixes #3299 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3299
改动
issue #3290 / PR #3298 修掉了 form.tsx「必填只画星号、控件无必填状态」的缺陷;本 PR 按 #3299 清单把其范围栅栏之外的五处逐一收敛到同一参照形状(
EmbeddableForm.tsx:481,489):aria-required={required || undefined}(可选字段不带属性,而不是写 "false");aria-hidden="true"(必填状态只经状态通道播报一次,不再折进可访问名被读成 "asterisk")。packages/app-shell/src/views/ActionParamDialog.tsxaria-required,经 fields 的toDomProps白名单(aria-*前缀放行,#3291/#3313)落到真实控件packages/app-shell/src/views/CreateViewDialog.tsxaria-required="true"packages/components/src/custom/action-param-dialog.tsxpackages/components/src/custom/field.tsxFieldContainer的 Slot 注入id/aria-describedby/aria-invalid同通道补一个aria-required,一处覆盖全部使用方;其星号是 CSS 伪元素、本就不进 a11y 树,无需改packages/plugin-detail/src/InlineCreateRelated.tsx刻意不用原生
required(#3290 裁决):这些宿主各自有校验(requiredError消息 /isCreateValid门控 / 提交时校验),原生 required 会让浏览器约束校验气泡与之双轨。issue「明确排除」段照单全收:renderers/form/{input,textarea,select,checkbox}.tsx与basic/text-input.tsx已设原生 required 且无双轨问题,不动。不动 spec、不动 widget props 契约(
aria-required已在既有 widget props 类型里,无需新键)。验证
pnpm exec vitest run五个新测试文件 + 既有ActionParamDialog.test.tsx/ActionParamDialog.uploading.test.tsxturbo run type-check --filter=@object-ui/components --filter=@object-ui/app-shell --filter=@object-ui/plugin-detail破坏验证实录(摘掉 → 红 → 还原 → 绿):
custom/field.tsx摘掉 Slot 注入的aria-required→field-container-aria-required.test.tsx5 例中 4 例红(sets aria-required="true" on the slotted control/never sets the native required/coexists with the pre-existing Slot injections/keeps the label association intact)→ 还原全绿。这是承重位:一处覆盖 FieldContainer 全部使用方。app-shell/ActionParamDialog.tsx摘掉默认分支 Widget 的aria-required→ActionParamDialog.ariaRequired.test.tsx5 例中 2 例红 → 还原全绿。该用例走真实字段 widget 全链路(host → widget props →toDomProps→ DOM),widget 侧若吞掉aria-*同样会红。changeset:
@object-ui/app-shell/@object-ui/components/@object-ui/plugin-detail各 patch(fixed group,无 major)。按 push-first 纪律:scoped 测试全绿 + 破坏验证完成后即推送;三个包的全量回归随后本地补跑,并由 CI 把关。
🤖 Generated with Claude Code
https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
Generated by Claude Code