Skip to content

fix(text-input): expose an empty labelled TextInput to screen readers - #5199

Open
datsiuk-ck wants to merge 1 commit into
callstack:mainfrom
datsiuk-ck:fix/textinput-a11y-resting-label
Open

datsiuk-ck wants to merge 1 commit into
callstack:mainfrom
datsiuk-ck:fix/textinput-a11y-resting-label

Conversation

@datsiuk-ck

Copy link
Copy Markdown

Motivation

An empty, unfocused TextInput with a label was missing from the accessibility tree on iOS and Android, so screen readers skipped it until someone focused it. Every untouched form started in this state. The input's wrapper took the label's float opacity, which is 0 while the label rests, and both platforms drop views with opacity 0 from accessibility.

This PR:

  • Keeps the input at full opacity while the label rests (it is empty and its placeholder is blank, so nothing visible changes), and fades it in only once the label floats, as before.
  • Always applies that style (opacity 1 without a label). Before, a field focused once and then left without a label kept a stale opacity of 0, so its placeholder and typed text were invisible.
  • Rests the placeholder at '' instead of ' '. Once the field was reachable, TalkBack announced it as "Space, edit box" instead of its label. iOS multiline fields keep ' ' (TextInput placeholder remains empty when multiline is true and the placeholder is set after certain timeout react/react-native#31573).

Related issue

Fixes #5197

Screenshots / Videos

Screen readers for unfocused text input

Before After
Android Impossible to select a field with a screen reader: image image
iOS Impossible to select a field with a screen reader: image image

Label removed after the field was focused once, then typing "hello":

Before After
Android image image
iOS image image

Test plan

  1. Render <TextInput label="Email" supportingText="We never share it" placeholder="you@example.com" value={email} onChangeText={setEmail} /> and leave it empty.
  2. Android with TalkBack on: touch the field. It is announced as "Email, We never share it, you@example.com. Edit box".
  3. iOS simulator with Accessibility Inspector: point at the field. It is a text field labelled "Email, We never share it, you@example.com".
  4. Focus the field: the placeholder and any prefix/suffix still fade in as the label floats. Same for a multiline field.
  5. Repro from the issue: focus the field, blur it while empty, remove the label, focus and type. The placeholder and the typed text show.

While the label rested, the input's wrapper had opacity 0, and iOS and
Android leave views with opacity 0 out of the accessibility tree: an empty,
unfocused labelled field was hidden from screen readers. The input now keeps
full opacity while the label rests and fades in once the label floats. The
style always applies, so a field whose label is removed no longer keeps a
stale opacity of 0 (placeholder and text stayed invisible).

While the label rests, the placeholder is now empty instead of ' ':
TalkBack read the blank aloud ("Space, edit box") instead of the label.
iOS multiline fields keep ' ' (react-native#31573).

Fixes callstack#5197
@github-actions

Copy link
Copy Markdown

Found potential problems with the pull request:

  • The description is too long. Please keep it under 1000 characters.

@Doberjohn Doberjohn added this to the 6.0.0 milestone Nov 10, 2026

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TextInput: an empty, unfocused TextInput with a label is hidden from screen readers

2 participants