Skip to content

form.tsx 全屏文本编辑对话框拿不到字段 label:标题恒为通用「编辑文本」,展开按钮的无障碍名在同一表单上完全一样 #3393

Description

@yinlianghui

在实现 #3272(PR #3392)时发现,未在该 PR 内修改 —— 那一单的范围是「把硬编码英文接进 i18n」,而这一条是数据没送到,属于行为缺陷,修法要动 props 传递。

现象

packages/components/src/renderers/form/form.tsx 内置 textarea 分支:

case 'textarea': {
  const { mobile_fullscreen, fullscreen, label } = fieldProps as any;

这里的 label 恒为 undefined。原因在上游 renderFormField 的字段解构 —— label...fieldProps 之前就被单独取走了:

const {
  name,
  label,
  description,
  type = 'input',
  ...
  ...fieldProps
} = field;

renderFieldComponent唯一调用点展开的是 ...fieldProps,并没有把 label 再补回去。那个 props 对象里显式补了 field / inputType / options / placeholder / disabled / readonly / emptyHint / dataSource / dependentValues / dependsOnLabels / validation 等等,唯独没有 label。全文件 grep,props 对象里没有任何一处 label:

后果(用户可见)

FullscreenTextarea 里两处依赖 label 的分支从来没有被走到:

  1. 对话框标题 {label ?? t('form.fullscreen.title')} —— 一个叫「备注」的长文本字段,点开全屏编辑,标题恒为通用的「编辑文本」,而不是字段名。作者写 label ?? … 显然是想要字段名兜个通用词,结果通用词成了唯一结果。
  2. 展开按钮的无障碍名 t('form.fullscreen.toggle', { label: label ?? t('form.fullscreen.textFallback') })(form.tsx 仍有一批用户可见的硬编码英文(全屏文本编辑对话框、Submit/Cancel 默认值、required aria-label) #3272 之前是模板串 Edit ${label ?? 'text'} fullscreen)—— 屏幕阅读器恒读「全屏编辑文本」。一张有三个长文本字段的表单上,三个展开按钮的无障碍名完全一样,读屏用户无法区分自己要展开的是哪个字段。这是 ADR-0054 之外的一条独立可达性问题,不是纯视觉问题。

旁证:ESLint 早就在同一分支的下一行报着 '_label' is assigned a value but never used

const { label: _label, ...rest } = stripRendererOnlyProps(fieldProps);

那一行的意图是「别让 label 落到 DOM 属性上」,而它要防的东西根本就没来。

修法建议

label 补进调用点的 props 对象即可(和 placeholder / emptyHint 一样显式传递),然后确认 stripRendererOnlyProps / stripRegisteredFieldProps 仍把它挡在 DOM 之外 —— _label 那一行届时就真的开始起作用了。

建议只给内置分支补,不要顺手改注册路径:注册型 field widget 走的是 FieldWidgetProps 契约,widget 已经能从 field 元数据里读到 label,再多送一路 label prop 是否合适需要对着那份契约单独确认(#3233 刚把「哪条 registry 入口决定哪份契约」收敛过一次,别在这里又开一个口)。

证据等级

静态证据(读 form.tsx 的三处相关源码 + 全文件 grep + 现成的 ESLint 告警),未做浏览器复现。「label 恒为 undefined」是可机械复核的事实:在 renderFieldComponent 入口打印 props 即可确认。

关联

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions