Skip to content

Backport macOS accessibility and TextInput fixes to 0.81-stable, with Paper validation #3135

Open

Description

@JasonVMo

Summary

Backport the macOS accessibility and TextInput fixes from main (#3136) to 0.81-stable, and finish the Paper (old architecture) work that can't be done on main. main no longer builds the legacy architecture, so the Paper code paths in those commits are untested.

FluentUI React Native applies these fixes to react-native-macos 0.81.9 through a Yarn patch (added in microsoft/fluentui-react-native#4386). It can remove the patch once a 0.81 release contains them.

Commits to backport

Cherry-pick in order. Each commit builds on its own; the last one is optional.

# Commit Change
1 68644c74c3 RCTConvert: convert each array element with the ARIA role table
2 533d408e74 Fabric: role from role / accessibilityRole, written to the accessibility element; legacy textbox mapping
3 deb87cffa6 Fabric: disabled, selected and expanded state on the accessibility element
4 10be049e17 Read-only vs. disabled TextInput (single-line and multiline, Paper and Fabric)
5 676c01f0c4 Fabric: one Tab stop per TextInput
6 a40ec92a3d Optional: recycled TextInputs keep their default role when the backing view is swapped

Cherry-pick dry run against 0.81-stable (41bc5d5eb4)

  • All native changes apply cleanly.
  • Commits 2 and 3 conflict only in packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js. Resolve by adding the two macOS examples to the 0.81 version of the file.

Follow .ai/commands/backport.md: branch 0.81/user/jasonvmo/a11y-fixes, PR titles fix(0.81, macos): …. PRs to 0.81-stable also need a changeset (yarn change:check).

Paper work

These Paper paths changed but could not be exercised on main:

  • Read-only: a single-line field with editable={false} is reachable with Tab, its text can be selected and copied, typing is rejected, and it reports AXEnabled = YES. The editable prop reaches RCTUITextField through RCT_REMAP_VIEW_PROPERTY(editable, backedTextInputView.editable, BOOL).
  • Disabled: with accessibilityState={{disabled: true}}, single-line and multiline fields are skipped by Tab, refuse click focus, and report AXEnabled = NO. Paper routes the prop through -[RCTBaseTextInputView reactAccessibilityElement] to the new -setAccessibilityState: overrides on RCTUITextField and RCTUITextView.
  • Prop removal: removing accessibilityState entirely, not just passing {disabled: false}, re-enables the field. This relies on the new nil handling in RCT_CUSTOM_VIEW_PROPERTY(accessibilityState, …).
  • Wrapper focus: RCTBaseTextInputView already returns NO from canBecomeKeyView. However, -[RCTView acceptsFirstResponder] returns focusable || super, and TextInput defaults focusable to true. Check whether clicking the wrapper outside the editor makes it first responder or sends an extra focus event. If it does, add the acceptsFirstResponder override that the Fabric component view now has.
  • Roles: accessibilityRole="textbox" reports AXTextField through the new legacy mapping.
  • Tab stops: a row of three single-line fields, and a multiline field, each take one Tab press in each direction.
  • Appearance: AppKit's disabled styling now applies to disabled fields instead of read-only ones. Check text and placeholder colors.

Fabric re-check on 0.81

Run the RNTester examples added by the commits on the new architecture:

  • Accessibility: "Roles from role and accessibilityRole" and "Disabled, selected and expanded state".
  • TextInput: "Read-only and disabled" and "Tab stops".

Commit 5 makes the RNTester-macOS window recalculate its key-view loop. Without that change, Tab doesn't move between React Native views in RNTester.

Downstream check

Before tagging the release, point FluentUI React Native at a local build and run yarn storybook smoke --macos --mode stories-and-tests and its --paper variant. Use the selectors components-*--*focus*, components-dropdown--*, components-menu*--* and native-modern-callout--*. With the patch these pass with zero skips: 19/19 shared focus, 8/8 Dropdown, 8/8 Menu and 16/16 Callout. The release should pass the same cases unpatched.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions