Skip to content

Commit c0cf8d9

Browse files
chore: remove hover effect & add cursor: pointer (#122)
* chore: remove hover effect * fix: set cursor pointer by default, update tests * feat(iOS): Implement cursor style prop # Conflicts: # packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts --------- Co-authored-by: Saad Najmi <[email protected]> # Conflicts: # packages/react-native/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap # packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js # packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js
1 parent 1d44e27 commit c0cf8d9

File tree

27 files changed

+402
-164
lines changed

27 files changed

+402
-164
lines changed

packages/react-native/Libraries/Components/Pressable/Pressable.js

+12-15
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import type {
2020
AccessibilityState,
2121
AccessibilityValue,
2222
} from '../View/ViewAccessibility';
23-
import type {HoverEffect} from '../View/ViewPropTypes';
2423

2524
import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
2625
import usePressability from '../../Pressability/usePressability';
2726
import {type RectOrSize} from '../../StyleSheet/Rect';
27+
import StyleSheet from '../../StyleSheet/StyleSheet';
2828
import useMergeRefs from '../../Utilities/useMergeRefs';
2929
import View from '../View/View';
3030
import useAndroidRippleForView, {
@@ -33,18 +33,12 @@ import useAndroidRippleForView, {
3333
import * as React from 'react';
3434
import {useImperativeHandle, useMemo, useRef, useState} from 'react';
3535

36-
const defaultHoverEffect: HoverEffect = 'highlight';
37-
3836
type ViewStyleProp = $ElementType<React.ElementConfig<typeof View>, 'style'>;
3937

4038
export type StateCallbackType = $ReadOnly<{|
4139
pressed: boolean,
4240
|}>;
4341

44-
type VisionOSProps = $ReadOnly<{|
45-
visionos_hoverEffect?: ?HoverEffect,
46-
|}>;
47-
4842
type Props = $ReadOnly<{|
4943
/**
5044
* Accessibility.
@@ -200,10 +194,6 @@ type Props = $ReadOnly<{|
200194
* https://github.com/facebook/react-native/issues/34424
201195
*/
202196
'aria-label'?: ?string,
203-
/**
204-
* Props needed for visionOS.
205-
*/
206-
...VisionOSProps,
207197
|}>;
208198

209199
/**
@@ -243,7 +233,6 @@ function Pressable(props: Props, forwardedRef): React.Node {
243233
style,
244234
testOnly_pressed,
245235
unstable_pressDelay,
246-
visionos_hoverEffect = defaultHoverEffect,
247236
...restProps
248237
} = props;
249238

@@ -352,15 +341,23 @@ function Pressable(props: Props, forwardedRef): React.Node {
352341
{...restPropsWithDefaults}
353342
{...eventHandlers}
354343
ref={mergedRef}
355-
style={typeof style === 'function' ? style({pressed}) : style}
356-
collapsable={false}
357-
visionos_hoverEffect={visionos_hoverEffect}>
344+
style={[
345+
styles.pressable,
346+
typeof style === 'function' ? style({pressed}) : style,
347+
]}
348+
collapsable={false}>
358349
{typeof children === 'function' ? children({pressed}) : children}
359350
{__DEV__ ? <PressabilityDebugView color="red" hitSlop={hitSlop} /> : null}
360351
</View>
361352
);
362353
}
363354

355+
const styles = StyleSheet.create({
356+
pressable: {
357+
cursor: 'pointer',
358+
},
359+
});
360+
364361
function usePressState(forcePressed: boolean): [boolean, (boolean) => void] {
365362
const [pressed, setPressed] = useState(false);
366363
return [pressed || forcePressed, setPressed];

packages/react-native/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap

+80
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ exports[`<Pressable /> should render as expected: should deep render when mocked
3131
onResponderTerminate={[Function]}
3232
onResponderTerminationRequest={[Function]}
3333
onStartShouldSetResponder={[Function]}
34+
style={
35+
Array [
36+
Object {
37+
"cursor": "pointer",
38+
},
39+
undefined,
40+
]
41+
}
3442
>
3543
<View />
3644
</View>
@@ -67,6 +75,14 @@ exports[`<Pressable /> should render as expected: should deep render when not mo
6775
onResponderTerminate={[Function]}
6876
onResponderTerminationRequest={[Function]}
6977
onStartShouldSetResponder={[Function]}
78+
style={
79+
Array [
80+
Object {
81+
"cursor": "pointer",
82+
},
83+
undefined,
84+
]
85+
}
7086
>
7187
<View />
7288
</View>
@@ -115,6 +131,14 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
115131
onResponderTerminate={[Function]}
116132
onResponderTerminationRequest={[Function]}
117133
onStartShouldSetResponder={[Function]}
134+
style={
135+
Array [
136+
Object {
137+
"cursor": "pointer",
138+
},
139+
undefined,
140+
]
141+
}
118142
>
119143
<View />
120144
</View>
@@ -151,6 +175,14 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
151175
onResponderTerminate={[Function]}
152176
onResponderTerminationRequest={[Function]}
153177
onStartShouldSetResponder={[Function]}
178+
style={
179+
Array [
180+
Object {
181+
"cursor": "pointer",
182+
},
183+
undefined,
184+
]
185+
}
154186
>
155187
<View />
156188
</View>
@@ -203,6 +235,14 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
203235
onResponderTerminate={[Function]}
204236
onResponderTerminationRequest={[Function]}
205237
onStartShouldSetResponder={[Function]}
238+
style={
239+
Array [
240+
Object {
241+
"cursor": "pointer",
242+
},
243+
undefined,
244+
]
245+
}
206246
>
207247
<View />
208248
</View>
@@ -239,6 +279,14 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
239279
onResponderTerminate={[Function]}
240280
onResponderTerminationRequest={[Function]}
241281
onStartShouldSetResponder={[Function]}
282+
style={
283+
Array [
284+
Object {
285+
"cursor": "pointer",
286+
},
287+
undefined,
288+
]
289+
}
242290
>
243291
<View />
244292
</View>
@@ -293,6 +341,14 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
293341
onResponderTerminate={[Function]}
294342
onResponderTerminationRequest={[Function]}
295343
onStartShouldSetResponder={[Function]}
344+
style={
345+
Array [
346+
Object {
347+
"cursor": "pointer",
348+
},
349+
undefined,
350+
]
351+
}
296352
>
297353
<View />
298354
</View>
@@ -329,6 +385,14 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
329385
onResponderTerminate={[Function]}
330386
onResponderTerminationRequest={[Function]}
331387
onStartShouldSetResponder={[Function]}
388+
style={
389+
Array [
390+
Object {
391+
"cursor": "pointer",
392+
},
393+
undefined,
394+
]
395+
}
332396
>
333397
<View />
334398
</View>
@@ -391,6 +455,14 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
391455
onResponderTerminate={[Function]}
392456
onResponderTerminationRequest={[Function]}
393457
onStartShouldSetResponder={[Function]}
458+
style={
459+
Array [
460+
Object {
461+
"cursor": "pointer",
462+
},
463+
undefined,
464+
]
465+
}
394466
>
395467
<View />
396468
</View>
@@ -427,6 +499,14 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
427499
onResponderTerminate={[Function]}
428500
onResponderTerminationRequest={[Function]}
429501
onStartShouldSetResponder={[Function]}
502+
style={
503+
Array [
504+
Object {
505+
"cursor": "pointer",
506+
},
507+
undefined,
508+
]
509+
}
430510
>
431511
<View />
432512
</View>

packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js

+13-11
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
*/
1010

1111
import type {ColorValue} from '../../StyleSheet/StyleSheet';
12-
import type {HoverEffect} from '../View/ViewPropTypes';
1312
import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
1413

1514
import View from '../../Components/View/View';
@@ -33,15 +32,10 @@ type IOSProps = $ReadOnly<{|
3332
hasTVPreferredFocus?: ?boolean,
3433
|}>;
3534

36-
type VisionOSProps = $ReadOnly<{|
37-
hoverEffect?: ?HoverEffect,
38-
|}>;
39-
4035
type Props = $ReadOnly<{|
4136
...React.ElementConfig<TouchableWithoutFeedback>,
4237
...AndroidProps,
4338
...IOSProps,
44-
...VisionOSProps,
4539

4640
activeOpacity?: ?number,
4741
underlayColor?: ?ColorValue,
@@ -335,10 +329,13 @@ class TouchableHighlight extends React.Component<Props, State> {
335329
accessibilityElementsHidden={
336330
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden
337331
}
338-
style={StyleSheet.compose(
339-
this.props.style,
340-
this.state.extraStyles?.underlay,
341-
)}
332+
style={[
333+
styles.touchable,
334+
StyleSheet.compose(
335+
this.props.style,
336+
this.state.extraStyles?.underlay,
337+
),
338+
]}
342339
onLayout={this.props.onLayout}
343340
hitSlop={this.props.hitSlop}
344341
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
@@ -347,7 +344,6 @@ class TouchableHighlight extends React.Component<Props, State> {
347344
nextFocusLeft={this.props.nextFocusLeft}
348345
nextFocusRight={this.props.nextFocusRight}
349346
nextFocusUp={this.props.nextFocusUp}
350-
visionos_hoverEffect={this.props.hoverEffect}
351347
focusable={
352348
this.props.focusable !== false && this.props.onPress !== undefined
353349
}
@@ -386,6 +382,12 @@ class TouchableHighlight extends React.Component<Props, State> {
386382
}
387383
}
388384

385+
const styles = StyleSheet.create({
386+
touchable: {
387+
cursor: 'pointer',
388+
},
389+
});
390+
389391
const Touchable = (React.forwardRef((props, hostRef) => (
390392
<TouchableHighlight {...props} hostRef={hostRef} />
391393
)): React.AbstractComponent<

packages/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type * as React from 'react';
1111
import {Constructor} from '../../../types/private/Utilities';
1212
import {TimerMixin} from '../../../types/private/TimerMixin';
1313
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
14-
import {HoverEffect, TVParallaxProperties} from '../View/ViewPropTypes';
14+
import {TVParallaxProperties} from '../View/ViewPropTypes';
1515
import {TouchableMixin} from './Touchable';
1616
import {TouchableWithoutFeedbackProps} from './TouchableWithoutFeedback';
1717

@@ -86,11 +86,6 @@ export interface TouchableOpacityProps
8686
* @platform android
8787
*/
8888
tvParallaxProperties?: TVParallaxProperties | undefined;
89-
90-
/**
91-
* Hover style to apply to the view. Only supported on visionOS.
92-
*/
93-
visionos_hoverEffect?: HoverEffect | undefined;
9489
}
9590

9691
/**

packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js

+8-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
*/
1010

1111
import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
12-
import type {HoverEffect} from '../View/ViewPropTypes';
1312
import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
1413

1514
import Animated from '../../Animated/Animated';
@@ -19,11 +18,10 @@ import Pressability, {
1918
} from '../../Pressability/Pressability';
2019
import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
2120
import flattenStyle from '../../StyleSheet/flattenStyle';
21+
import StyleSheet from '../../StyleSheet/StyleSheet';
2222
import Platform from '../../Utilities/Platform';
2323
import * as React from 'react';
2424

25-
const defaultHoverEffect: HoverEffect = 'highlight';
26-
2725
type TVProps = $ReadOnly<{|
2826
hasTVPreferredFocus?: ?boolean,
2927
nextFocusDown?: ?number,
@@ -33,14 +31,9 @@ type TVProps = $ReadOnly<{|
3331
nextFocusUp?: ?number,
3432
|}>;
3533

36-
type VisionOSProps = $ReadOnly<{|
37-
visionos_hoverEffect?: ?HoverEffect,
38-
|}>;
39-
4034
type Props = $ReadOnly<{|
4135
...React.ElementConfig<TouchableWithoutFeedback>,
4236
...TVProps,
43-
...VisionOSProps,
4437

4538
activeOpacity?: ?number,
4639
style?: ?ViewStyleProp,
@@ -138,10 +131,6 @@ type State = $ReadOnly<{|
138131
*
139132
*/
140133
class TouchableOpacity extends React.Component<Props, State> {
141-
static defaultProps: {|visionos_hoverEffect: HoverEffect|} = {
142-
visionos_hoverEffect: defaultHoverEffect,
143-
};
144-
145134
state: State = {
146135
anim: new Animated.Value(this._getChildStyleOpacityWithDefault()),
147136
pressability: new Pressability(this._createPressabilityConfig()),
@@ -287,7 +276,7 @@ class TouchableOpacity extends React.Component<Props, State> {
287276
accessibilityElementsHidden={
288277
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden
289278
}
290-
style={[this.props.style, {opacity: this.state.anim}]}
279+
style={[styles.touchable, this.props.style, {opacity: this.state.anim}]}
291280
nativeID={this.props.id ?? this.props.nativeID}
292281
testID={this.props.testID}
293282
onLayout={this.props.onLayout}
@@ -298,7 +287,6 @@ class TouchableOpacity extends React.Component<Props, State> {
298287
nextFocusUp={this.props.nextFocusUp}
299288
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
300289
hitSlop={this.props.hitSlop}
301-
visionos_hoverEffect={this.props.visionos_hoverEffect}
302290
focusable={
303291
this.props.focusable !== false && this.props.onPress !== undefined
304292
}
@@ -336,6 +324,12 @@ class TouchableOpacity extends React.Component<Props, State> {
336324
}
337325
}
338326

327+
const styles = StyleSheet.create({
328+
touchable: {
329+
cursor: 'pointer',
330+
},
331+
});
332+
339333
const Touchable = (React.forwardRef((props, ref) => (
340334
<TouchableOpacity {...props} hostRef={ref} />
341335
)): React.AbstractComponent<Props, React.ElementRef<typeof Animated.View>>);

0 commit comments

Comments
 (0)