Skip to content

Commit 7736dbc

Browse files
committed
Initial version of the proposal
1 parent 8995818 commit 7736dbc

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
title: Hover style API for iPad / Apple Vision Pro
3+
author:
4+
- Oskar Kwaśniewski
5+
- Saad Najmi
6+
date: 08.01.2023
7+
---
8+
9+
# RFC0000: Hover style API for iPad / Apple Vision Pro
10+
11+
## Summary
12+
13+
iPad supports hover style effects when using an external mouse/trackpad. This effect illuminates the UIView in two configurable ways: lift or highlight. This proposal intends to add support for this API in React Native. This API is also used by visionOS to display the hover effect when a user looks at the view.
14+
15+
The native API this feature is basing on: https://developer.apple.com/documentation/uikit/uihoverstyle (iOS 17+). There is an older version of this API supporting iOS 13.4+ https://developer.apple.com/documentation/uikit/uipointerstyle
16+
17+
## Basic example
18+
19+
This API would introduce an additional prop to UIView (which is used to render touchable/pressable elements).
20+
21+
```jsx
22+
<Pressable hoverEffect=”lift” onPress={onPressFunction}>
23+
<Text>I'm pressable!</Text>
24+
</Pressable>
25+
```
26+
27+
The hover effect automatically adapts to view’s corner radius.
28+
29+
Example of highlight effect:
30+
31+
https://github.com/react-native-community/discussions-and-proposals/assets/52801365/a1ace4ac-44c1-45e6-afbe-6e0b0f05f74d
32+
33+
## Motivation
34+
35+
Controlling hover style allows React Native developers to provide a much better user experience on iPad and Apple Vision Pro, allowing them to seamlessly interact with React Native applications using the mouse.
36+
37+
Additionally, We have lots of React Native experiences in brownfield contexts at Microsoft. The value add of React Native over something like a webview is that we can access the system APIs, and provide the best UX for the platform. This includes iPadOS / visionOS, where hover events are now a part of the UX language and built into UIKit controls. In order for React Native experiences to thrive living side by side with native experiences, we would live to have as close UX as possible.
38+
39+
This API can work side by side with the Pointer Events API. Users can choose to either spin up their own custom interactions with the pointer events API, or use Apple OS default. Adding a hover effect shouldn’t effect pointer events being fired or not. https://reactnative.dev/blog/2022/12/13/pointer-events-in-react-native
40+
41+
## Detailed design
42+
43+
_Disclaimer: I will discuss the design for New Architecture, but the API can be easily backported._
44+
45+
The API should be opt-in to avoid breaking current iPad apps. The implementation bases on extending `RCTView` with a new prop of type `std::string`.
46+
47+
Next inside of `RCTViewComponentView` `- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps`` method:
48+
49+
```objc
50+
if (oldViewProps.hoverEffect != newViewProps.hoverEffect) {
51+
[self updateHoverEffect:[NSString stringWithUTF8String:newViewProps.hoverEffect.c_str()]];
52+
}
53+
54+
In the code above we are detecting props update, and calling updateHoverEffect method:
55+
56+
- (void) updateHoverEffect:(NSString*)hoverEffect {
57+
if (hoverEffect == nil || [hoverEffect isEqualToString:@""]) {
58+
self.hoverStyle = nil;
59+
return;
60+
}
61+
62+
UIShape *shape = [UIShape rectShapeWithCornerRadius:self.layer.cornerRadius];
63+
id<UIHoverEffect> effect;
64+
65+
if ([hoverEffect isEqualToString:@"lift"]) {
66+
effect = [UIHoverLiftEffect effect];
67+
} else if ([hoverEffect isEqualToString:@"highlight"]) {
68+
effect = [UIHoverHighlightEffect effect];
69+
}
70+
71+
if (hoverEffect != nil) {
72+
self.hoverStyle = [UIHoverStyle styleWithEffect:effect shape:shape];
73+
}
74+
}
75+
```
76+
77+
Here we initialize a new `UIShape` which reassembles the current’s view layer `cornerRadius`. Next we are creating a `UIHoverEffect` instance based on the value passed by user.
78+
79+
The current API implementation might need some polish to correctly retrieve corner radius.
80+
81+
## Drawbacks
82+
83+
- Apple only API
84+
- Only Android equivalent I found is: https://developer.android.com/reference/android/view/MotionEvent which doesn’t provide any built-in effect but allows to create custom ones.
85+
- There might be different plan for the Pointer Events API.
86+
87+
## Alternatives
88+
89+
- This API might be also implemented using Pointer Events API by detecting hover and applying some custom styling to the view but this would be less performant than using native solution.
90+
- This feature could be also implemented in user space by creating their own subclass of UIView and wrapping every element with it.
91+
92+
## Adoption strategy
93+
94+
Users can opt-in without any breaking changes.
95+
96+
## How we teach this
97+
98+
Describe this prop in the documentation. Add section to docs about iPad development.
99+
100+
## Unresolved questions
101+
102+
- How does it fit with Pointer Events API?

0 commit comments

Comments
 (0)