Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FocusZone (macOS): New prop to ignore OS keyboard shortcut preference #2267

Merged
merged 10 commits into from
Oct 27, 2022

Conversation

Saadnajmi
Copy link
Collaborator

@Saadnajmi Saadnajmi commented Oct 24, 2022

Platforms Impacted

  • iOS
  • macOS
  • win32 (Office)
  • windows
  • android

Description of changes

This change allows FocusZone to make Menu always focusable on macOS, regardless of the user's system preference. This matches what native macOS Context menus do.

Verification

Tested turning the system setting on and off, and verified that you could still keyboard through a menu.

Pull request checklist

This PR has considered (when applicable):

  • Automated Tests
  • Documentation and examples
  • Keyboard Accessibility
  • Voiceover
  • Internationalization and Right-to-left Layouts

@Saadnajmi Saadnajmi marked this pull request as ready for review October 26, 2022 20:58
@Saadnajmi Saadnajmi requested a review from a team as a code owner October 26, 2022 20:58
@Saadnajmi Saadnajmi changed the title [DRAFT] FocusZone (macOS): New prop to ignore OS keyboard shortcut preference FocusZone (macOS): New prop to ignore OS keyboard shortcut preference Oct 26, 2022
@Saadnajmi Saadnajmi merged commit d5c85ec into microsoft:main Oct 27, 2022
@Saadnajmi Saadnajmi deleted the fz-prop branch October 27, 2022 20:36
Saadnajmi added a commit to Saadnajmi/fluentui-react-native that referenced this pull request Nov 9, 2022
ghost pushed a commit that referenced this pull request Nov 18, 2022
… views (#2329)

### Platforms Impacted
- [ ] iOS
- [x] macOS
- [ ] win32 (Office)
- [ ] windows
- [ ] android

### Description of changes

This is a simpler version of #2267 . Instead of adding a new prop to differentiate whether we focus on key views vs first responders, this one will just... focus on first responders unconditionally.

The reasoning is as follows:

1) FocusZone itself doesn't override `canBecomeKeyView. So FocusZone itself respects the system keyboard navigation preference.
2) FocusZone itself is pretending to be "one big focusable view" to the eyes of Appkit. Its job is to move focus inside itself between focusable views. Once it gains focus (via the key view loop or programmatically), it probably doesn't matter whether its children were key views. If you're using a FocusZone for your custom control, you probably still want the keyboard events to work regardless.

How this affects components:

- For the case of ContextualMenu, we call `focusZoneRef.current.focus()` once the menu is opened. This will force focus on the Menu regardless of the OS preference (which we want), and then with this change keyboard navigation will work.
- For the case of Radiogroup: Native Appkit RadioGroups are not key views if the keyboard navigation preference is disabled, and you can't move focus or arrow key through them at all. With our JS Radiogroup (and Native RadioGroup), this behavior should be the same, since the enclosing FocusZone will not become a key view.

### Verification

Locally side loaded the built `libRCTFocusZone.a` to test a partner scenario, and it worked fine with no regressions. Tested ContextualMenu and RadioGroup and didn't find any regressions. 


### Pull request checklist

This PR has considered (when applicable):
- [ ] Automated Tests
- [ ] Documentation and examples
- [ ] Keyboard Accessibility
- [ ] Voiceover
- [ ] Internationalization and Right-to-left Layouts
nakambo added a commit that referenced this pull request Jan 29, 2025
When a TextInput is not inside a FocusZone, it properly participates in the key view loop in that Tab\Shift+Tab will place focus on the inner `RCTUITextView`, instead of the outer `RCTBaseTextInputView` subclass. This is due to [overriding](https://github.com/microsoft/react-native-macos/blob/b7033b3513d98b20a08ec20abfe2b9bb712c68d4/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm#L1147C1-L1150C2) the `canBecomeKeyView` in that base class.

However, the FocusZone control does not look at that property -- instead it only considers `canBecomeFirstResponder`, as seen in #2329.  Although it seems like the logical next step to use `canBecomeKeyView` in the FocusZone, that was previously done with #2267 but later reverted in #2322 since it broke things downstream. Instead, we'll make a compromise and leak some of the text input implementation details into the focus zone -- if we're considering focusing a subclass of `RCTBaseTextInputView`, we'll instead use the containing `backedTextInputView`.

Testing:

* TI inside FZ is now properly focused (using the new case added to the FZ page)
* Verified all other cases on the FZ page
* Verified in the downstream scenario that prompted this investigation

Notes:

* I noticed that Shift+Ctrl+Tab does not move focus out of the containing FZ, but that has been determined to be a pre-existing issue, and thus isn't being addressed in this change.
nakambo added a commit that referenced this pull request Jan 29, 2025
* Fix TextInput focus when inside a FocusZone

When a TextInput is not inside a FocusZone, it properly participates in the key view loop in that Tab\Shift+Tab will place focus on the inner `RCTUITextView`, instead of the outer `RCTBaseTextInputView` subclass. This is due to [overriding](https://github.com/microsoft/react-native-macos/blob/b7033b3513d98b20a08ec20abfe2b9bb712c68d4/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm#L1147C1-L1150C2) the `canBecomeKeyView` in that base class.

However, the FocusZone control does not look at that property -- instead it only considers `canBecomeFirstResponder`, as seen in #2329.  Although it seems like the logical next step to use `canBecomeKeyView` in the FocusZone, that was previously done with #2267 but later reverted in #2322 since it broke things downstream. Instead, we'll make a compromise and leak some of the text input implementation details into the focus zone -- if we're considering focusing a subclass of `RCTBaseTextInputView`, we'll instead use the containing `backedTextInputView`.

Testing:

* TI inside FZ is now properly focused (using the new case added to the FZ page)
* Verified all other cases on the FZ page
* Verified in the downstream scenario that prompted this investigation

Notes:

* I noticed that Shift+Ctrl+Tab does not move focus out of the containing FZ, but that has been determined to be a pre-existing issue, and thus isn't being addressed in this change.
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.

4 participants