fix(text-input): correct MD3 states and accessibility - #5111
Open
likevy wants to merge 1 commit into
Open
Conversation
Filled indicator colors now follow the tokens: `onSurfaceVariant` at rest, `onSurface` on hover, and `onErrorContainer` when an invalid field is hovered. Outlined fields keep `outline` and ignore hover. Supporting text, the error and the counter are associated with the field instead of being folded into its accessible name: generated ids referenced by `aria-describedby` on web, and `accessibilityHint` on Android and iOS, which have no described-by relationship. Errors announce through `role="alert"`, an assertive Android live region, and a one-shot iOS announcement. An explicit `aria-invalid` or `aria-describedby` is preserved. An empty unfocused field no longer fades out of the native accessibility tree with the label animation, and a disabled input is read-only so it cannot be operated. BREAKING CHANGE: TextInput.Icon with any press handler requires aria-label or accessibilityLabel. Icons without press handlers are decorative.
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.
Motivation
TextInputis one of the MD3 reference components. The review found the filled active indicator using the wrong resting colour with no hover state, the field's supporting text, error and counter never programmatically associated with the input, and decorative accessories rendering as focusable buttons.This worth mentioning:
aria-label, so a screen reader read label and helper as one blob. It now carries a generatednativeIDreferenced byaria-describedbyon web. React Native 0.85 has no native described-by, so on Android and iOS the same text goes intoaccessibilityHint, which describes without renaming.role="alert", an assertive region on Android, and a one-shotAccessibilityInfoannouncement on iOS, which implements neither.aria-hiddenand unfocusable, so a plain leading icon no longer creates a tab stop that announces "button". With one, it requires an accessible name, enforced by the props type and a__DEV__warning.onSurfaceVariantat rest,onSurfacehovered,primaryfocused,errorinvalid,onErrorContainerinvalid and hovered. Outlined keepsoutlineand correctly does not react to hover.Also fixed: the field container was opacity-bound to the label animation, which faded an empty unfocused field out of the native accessibility tree, and a disabled input is now
readOnlyso it cannot be operated.aria-invalidandaria-describedbyare public props, and an explicit value wins over the derived one.Indicator values were verified against material-web's generated
_md-comp-filled-text-field.scss, since the spec site is JS-rendered.Related issue
The TextInput review checklist:
outline; MD3 usesonSurfaceVariant.onErrorContainer), missing for the same reason.aria-label, and the error isaria-live="polite"rather thanrole="alert". Associate them (aria-describedby/nativeID) and announce errors.IconButton(role="button") even when non-actionable; render decorative icons non-interactively and require names for actionable ones.Test plan
yarn lint,yarn typecheckandyarn testpass - 713 tests, 168 snapshots.35 new tests (TextInput: 62 to 97) in two new suites.
TextInputAccessibility.test.tsxcovers ID stability as helper text becomes an error, distinct IDs across fields sharing a testID, merged externalaria-describedby, web descriptions not duplicated into a hint, the iOS announcement firing once per changed message, the Android live regions, a disabled field staying read-only whenreadOnly={false}, decorative accessories rendering outside the accessibility tree with no button, named disabled accessories staying inoperable, and refs and layout callbacks surviving the decorative/actionable switch.TextInputStates.test.tsxpins the filled resting and hover colours without disturbing the focused or disabled indicator, and pins that outlined ignores hover.Manual, on the TextInput example screen, for both variants:
aria-labellogs a dev warning.onSurfaceVarianttoonSurface; with Error on,errortoonErrorContainer. Outlined does not change. Focus overrides hover.onSurfaceat 38%.Run on Android, iOS and web, plus a screen-reader pass.