Skip to content

fix(many): keep form field messages out of the control's accessible name#2625

Open
git-nandor wants to merge 1 commit into
masterfrom
INSTUI-4724_form_field_labels_should_not_include_message
Open

fix(many): keep form field messages out of the control's accessible name#2625
git-nandor wants to merge 1 commit into
masterfrom
INSTUI-4724_form_field_labels_should_not_include_message

Conversation

@git-nandor

@git-nandor git-nandor commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

INSTUI-4724

Summary

Form control messages render inside the wrapping , so screen readers were reading them as part of the field's accessible name (e.g. "Password Password must be at least 6 characters") instead of as a description.

Each single form control now points its accessible name at the label text only (aria-labelledby) and references the messages as its description (aria-describedby), so a screen reader announces the label first, then the messages. The wrapping is unchanged, so click-on-label focus is preserved.

Test plan

Tab through the given exaple and verify in DevTools Accessibility tab that the Name and Description values are correct. With a screen reader enabled, confirm that the label is announced as the field name, followed by a brief pause before the description is announced.

image
const messages = [{ type: 'error', text: 'This field has an error' }]

render(
  <View as="div" display="block" width="24rem">
    <Text as="p">
      Tab through and verify in DevTools Accessibility tab that the Name and Description values are correct. With a screen reader enabled, confirm that the label is announced as the field name, followed by a brief pause before the description is announced.
    </Text>

    <View as="div" margin="medium 0 0">
      <TextInput renderLabel="Text Input" messages={messages} />
    </View>
    <View as="div" margin="medium 0 0">
      <NumberInput renderLabel="Number Input" messages={messages} />
    </View>
    <View as="div" margin="medium 0 0">
      <TextArea label="Text Area" messages={messages} />
    </View>
    <View as="div" margin="medium 0 0">
      <Checkbox label="Checkbox (simple)" value="c1" messages={messages} />
    </View>
    <View as="div" margin="medium 0 0">
      <Checkbox
        label="Checkbox (toggle)"
        variant="toggle"
        value="c2"
        messages={messages}
      />
    </View>
    <View as="div" margin="medium 0 0">
      <RangeInput
        label="Range Input"
        name="range"
        min={0}
        max={100}
        defaultValue={50}
        messages={messages}
      />
    </View>
  </View>
)

Co-Authored-By: 🤖 Claude

@git-nandor git-nandor self-assigned this Jul 6, 2026
@git-nandor git-nandor requested a review from ToMESSKa July 6, 2026 16:48
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://instructure.design/pr-preview/pr-2625/

Built to branch gh-pages at 2026-07-08 15:15 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Visual regression report

No changes.

Status Count
Unchanged 32
Changed 0
New 0
Removed 0

📊 View full report

Baselines come from the visual-baselines branch. They refresh on every merge to master.

github-actions Bot pushed a commit that referenced this pull request Jul 6, 2026
@git-nandor git-nandor marked this pull request as ready for review July 7, 2026 10:18
Comment on lines +241 to +242
// Any consumer-provided `aria-labelledby` (e.g. Select's pill handling)
// takes precedence.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Select's pill handling doesn't use aria-labelledby anymore see #2616 (comment) so this is not a relevant example

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, modified

Form control messages (error/hint/success) render inside the wrapping <label>, so they were
read as part of the field's accessible name. Point each control's name at the label text via
aria-labelledby and reference the messages via aria-describedby, so screen readers announce
them as the field's description. Label click-to-focus is preserved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@git-nandor git-nandor force-pushed the INSTUI-4724_form_field_labels_should_not_include_message branch from 9e15d7b to 8d8c8f4 Compare July 8, 2026 15:11
@git-nandor git-nandor requested review from ToMESSKa and removed request for ToMESSKa July 8, 2026 15:11

@ToMESSKa ToMESSKa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A vitest test is failing, can you please check?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants