react-native-windows-samples icon indicating copy to clipboard operation
react-native-windows-samples copied to clipboard

Better Keyboard Shortcut support

Open rurikoaraki opened this issue 4 years ago • 4 comments

Proposal: Better Keyboard Shortcut support

Summary

Although supportKeyboard allows for implementing handling of keyboard shortcuts on a React Native Windows app, it seems that the XAML platform has good support for handling keyboard shortcuts through UIElement's KeyboardAccelerators property. We could potentially use it to expose a KeyboardShortcut prop (and similarly an AccessKey prop) on a Touchable, or use XAML's commanding system to have React Native support implementing keyboard shortcuts directly. This would save each app from implementing their own shortcut handling system by using supportKeyboard.

Motivation

Keyboard shortcuts are important to expose so that people can efficiently traverse an app. We also find supporting shortcuts important for keyboard accessibility of the app. The React Native Windows platform has a way to implement keyboard shortcuts by using the supportKeyboard API, but using supportKeyboard for implementing keyboard shortcuts puts a lot of onus on the app developer to make their own keyboard shortcut handling system and to get it right. Each app developer would have to figure out the best place to listen for key events, how to determine when shortcuts were pressed, how to know if a command should be handled based on app state, and implement that system themselves. The platform could make this system easier to implement by removing the need to do those things, and would also encourage keyboard shortcut implementation if it's made a prop on a particular component.

Another point to consider is that supportKeyboard relies on PreviewKeyDown and PreviewKeyUp, which fires based on focus placement, while keyboard shortcuts tend to be global (i.e. if you press the right keys, the event fires regardless of where focus is), which is a difference in behavior of the systems. While it’s possible to make it look like shortcuts are global if by using supportKeyboard, the developer may have to take extra steps managing focus or building native modules and having to explore and consider several solutions to make it happen because supportKeyboard relies on focus. If we hooked into the platform’s system directly, we could avoid these issues and differences in model.

This change should be considered for Windows first, as Windows is the first React Native platform that is heavily keyboard-focused.

Basic example

For example it might look like:

<TouchableHighlight
…
keyboardShortcut={keys: ‘[‘Control’, ‘N’], isEnabled: this.props.newEventButtonEnabled}
onPress={this.props.onNewEventButtonPressed}
…
/>

If the keyboard shortcut is invoked, it could fire the onPress callback

Open Questions

  • Does it make sense to support keyboard shortcuts specifically given that supportKeyboard can be used to implement keyboard shortcuts?
  • How would we handle key differences on different endpoints?
  • Is UIElement's KeyboardAccelerators property the best API to use for implementing this on Windows?

rurikoaraki avatar Aug 28 '19 22:08 rurikoaraki

I would like to sperate key and the modifiers. [RNW keyboard implementation]

export interface INativeKeyboardEvent {
  altKey: boolean;
  ctrlKey: boolean;
  metaKey: boolean;
  shiftKey: boolean;
  key: string;
  code: string;
  eventPhase: EventPhase;
}

XAML example,

          <KeyboardAccelerator 
            Modifiers="Control" 
            Key="C" 
            ScopeOwner="{x:Bind MyList }" />

react keyboard event

oolean altKey
number charCode
boolean ctrlKey
boolean getModifierState(key)
string key
number keyCode
string locale
number location
boolean metaKey
boolean repeat
boolean shiftKey
number which

licanhua avatar Oct 17 '19 17:10 licanhua

Upon discussion, we are scoping this down a bit -

  • Key events can be used to accomplish the local keyboard shortcuts in the client/app/component instead of adding APIs to the platform here.
  • There is a need for hooks to handle global keyboard shortcuts. This is being tracked with microsoft/react-native-windows#3449. A workaround exists for now, unblocked.
  • There is a need to add a property to accessibility that apps can set for narrating the shortcut key associated with an element. This is tracked by microsoft/react-native-windows#3450

Changing this proposal to a documentation/sample.

harinikmsft avatar Oct 17 '19 17:10 harinikmsft

We believe shortcut keys can be enabled through key events and will be providing a sample to show how that is accomplished. As part of the sample, the guidance for accessibility will be to add the shortcut key as a string to accessibilityHint which is the pattern used in other platforms.

We are punting on the below features for now:

harinikmsft avatar Oct 28 '20 18:10 harinikmsft

Any chance that sample exists yet? We're working on a new app that will ideally heavily embrace shortcuts, at this stage I'm guessing we'll need to write a native module? For example, we don't expect the user to be focused on an element for this to work, but instead will react based on active window.

jbcullis avatar Mar 17 '22 00:03 jbcullis