feat(components): PressableSurface with refined press feedback
This commit is contained in:
1 parent
9b02c10926
commit
fc42e1da43
2 files changed
+113
No files matched your search
@@ -0,0 +1,67 @@
|
||||
import React, { useCallback, type ReactNode } from 'react';
|
||||
import { Pressable, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
|
||||
import Animated, {
|
||||
Easing,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming,
|
||||
} from 'react-native-reanimated';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
readonly onPress?: () => void;
|
||||
readonly disabled?: boolean;
|
||||
readonly style?: StyleProp<ViewStyle>;
|
||||
readonly accessibilityLabel?: string;
|
||||
readonly testID?: string;
|
||||
};
|
||||
|
||||
export function PressableSurface({
|
||||
children,
|
||||
onPress,
|
||||
disabled,
|
||||
style,
|
||||
accessibilityLabel,
|
||||
testID,
|
||||
}: Props) {
|
||||
const scale = useSharedValue(1);
|
||||
const opacity = useSharedValue(1);
|
||||
|
||||
const onPressIn = useCallback(() => {
|
||||
scale.value = withTiming(0.96, { duration: 80, easing: Easing.out(Easing.quad) });
|
||||
opacity.value = withTiming(0.82, { duration: 80, easing: Easing.out(Easing.quad) });
|
||||
}, [scale, opacity]);
|
||||
|
||||
const onPressOut = useCallback(() => {
|
||||
scale.value = withTiming(1, { duration: 160, easing: Easing.out(Easing.quad) });
|
||||
opacity.value = withTiming(1, { duration: 160, easing: Easing.out(Easing.quad) });
|
||||
}, [scale, opacity]);
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => ({
|
||||
transform: [{ scale: scale.value }],
|
||||
opacity: opacity.value,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Animated.View style={animatedStyle}>
|
||||
<Pressable
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole={accessibilityLabel ? 'button' : undefined}
|
||||
disabled={disabled}
|
||||
onPress={onPress}
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
style={[styles.base, style]}
|
||||
testID={testID}
|
||||
>
|
||||
{children}
|
||||
</Pressable>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
alignSelf: 'stretch',
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user