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

[IOAPPX-428] Add the new useScaleAnimation and useListItemAnimation hooks + Add support for the reducedMotion a11y setting #358

Merged
merged 21 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
81501e0
Add the new `useScaleButton` hook to all the buttons
dmnplb Nov 14, 2024
16d7168
Update `jest` snapshots
dmnplb Nov 14, 2024
be35b1e
Rename `useAnimatedButton` to `useScaleAnimation`
dmnplb Nov 14, 2024
b9ec66a
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 14, 2024
d9b698b
Improve code of `TabItem` using the new `useScaleAnimation` hook
dmnplb Nov 15, 2024
e5c5526
Replace `useModuleSpringAnimation` with `useScaleAnimation`
dmnplb Nov 15, 2024
064ab03
Move `useScaleAnimation` into separate and exported `hooks` folder
dmnplb Nov 15, 2024
82215b8
Update path of the `useScaleAnimation` import
dmnplb Nov 15, 2024
aca2724
Apply the new `useListItemAnimation` to all the interactive `ListItem…
dmnplb Nov 15, 2024
232070b
Fix typo in the `PressableListItemBase` filename
dmnplb Nov 15, 2024
3c65997
Remove repeated code from other components by using `useScaleAnimation`
dmnplb Nov 15, 2024
b4159ae
Update `jest` snapshot
dmnplb Nov 15, 2024
e24cfdf
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 15, 2024
9024dfe
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 21, 2024
7e5fab0
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 21, 2024
cfb9d31
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 21, 2024
154531d
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Nov 26, 2024
cc0a5d6
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Dec 2, 2024
cdc6f47
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Dec 6, 2024
bc70475
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Dec 10, 2024
8c5a8af
Merge branch 'main' into IOAPPX-428-refactor-scale-effect-reduce-motion
dmnplb Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ jest.mock("react-native-reanimated", () => {
// The mock misses the `addWhitelistedUIProps` implementation
// So we override it with a no-op
// eslint-disable-next-line functional/immutable-data,@typescript-eslint/no-empty-function
Reanimated.default.addWhitelistedUIProps = () => {};
Reanimated.default.addWhitelistedUIProps = () => { };
// eslint-disable-next-line functional/immutable-data
Reanimated.useReducedMotion = () => false;

return Reanimated;
});
Expand Down
53 changes: 7 additions & 46 deletions src/components/alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from "react";
import React, { forwardRef, useCallback, useState } from "react";
import {
ColorValue,
GestureResponderEvent,
Expand All @@ -9,20 +9,12 @@ import {
TextLayoutEventData,
View
} from "react-native";
import Animated, {
Extrapolation,
SharedValue,
interpolate,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withSpring
} from "react-native-reanimated";
import Animated from "react-native-reanimated";
import { IOVisualCostants, useIOThemeContext } from "../../core";
import { IOScaleValues, IOSpringValues } from "../../core/IOAnimations";
import { IOColors, hexToRgba } from "../../core/IOColors";
import { IOAlertRadius } from "../../core/IOShapes";
import { IOAlertSpacing } from "../../core/IOSpacing";
import { useScaleAnimation } from "../../hooks";
import { WithTestID } from "../../utils/types";
import { IOIconSizeScale, IOIcons, Icon } from "../icons";
import { VSpacer } from "../spacer";
Expand Down Expand Up @@ -132,7 +124,7 @@ const mapVariantStatesDarkMode: Record<
}
};

export const Alert = React.forwardRef<View, AlertType>(
export const Alert = forwardRef<View, AlertType>(
(
{
variant,
Expand All @@ -146,8 +138,9 @@ export const Alert = React.forwardRef<View, AlertType>(
}: AlertType,
viewRef
): JSX.Element => {
const { onPressIn, onPressOut, scaleAnimatedStyle } =
useScaleAnimation("medium");
const { themeType } = useIOThemeContext();
const isPressed: SharedValue<number> = useSharedValue(0);

const [isMultiline, setIsMultiline] = useState(false);

Expand All @@ -158,38 +151,6 @@ export const Alert = React.forwardRef<View, AlertType>(
[]
);

// Scaling transformation applied when the button is pressed
const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState;

// Using a spring-based animation for our interpolations
const progressPressed = useDerivedValue(() =>
withSpring(isPressed.value, IOSpringValues.button)
);

// Interpolate animation values from `isPressed` values
const pressedAnimationStyle = useAnimatedStyle(() => {
// Scale down button slightly when pressed
const scale = interpolate(
progressPressed.value,
[0, 1],
[1, animationScaleValue],
Extrapolation.CLAMP
);

return {
transform: [{ scale }]
};
});

const onPressIn = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 1;
}, [isPressed]);
const onPressOut = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 0;
}, [isPressed]);

const mapVariantStates =
themeType === "light"
? mapVariantStatesLightMode
Expand Down Expand Up @@ -287,7 +248,7 @@ export const Alert = React.forwardRef<View, AlertType>(
fullWidth ? styles.spacingFullWidth : styles.spacingDefault,
{ backgroundColor: mapVariantStates[variant].background },
// Disable pressed animation when component is full width
!fullWidth && pressedAnimationStyle
!fullWidth && scaleAnimatedStyle
]}
>
{renderMainBlock()}
Expand Down
52 changes: 6 additions & 46 deletions src/components/alert/AlertEdgeToEdge.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import React, { useCallback, useMemo } from "react";
import React, { useMemo } from "react";
import {
GestureResponderEvent,
Pressable,
StyleSheet,
Text,
View
} from "react-native";
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withSpring
} from "react-native-reanimated";
import Animated from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import {
IOScaleValues,
IOSpringValues,
IOVisualCostants,
enterTransitionAlertEdgeToEdge,
enterTransitionAlertEdgeToEdgeContent,
Expand All @@ -30,6 +21,7 @@ import {
} from "../../core/IOColors";
import { IOAlertSpacing } from "../../core/IOSpacing";
import { IOStyles } from "../../core/IOStyles";
import { useScaleAnimation } from "../../hooks";
import { makeFontStyleObject } from "../../utils/fonts";
import { WithTestID } from "../../utils/types";
import { IOIconSizeScale, IOIcons, Icon } from "../icons";
Expand Down Expand Up @@ -105,42 +97,10 @@ export const AlertEdgeToEdge = ({
accessibilityHint,
testID
}: AlertEdgeToEdgeProps) => {
const isPressed: Animated.SharedValue<number> = useSharedValue(0);

const { onPressIn, onPressOut, scaleAnimatedStyle } =
useScaleAnimation("slight");
const insets = useSafeAreaInsets();

// Scaling transformation applied when the button is pressed
const animationScaleValue = IOScaleValues?.basicButton?.pressedState;

// Using a spring-based animation for our interpolations
const progressPressed = useDerivedValue(() =>
withSpring(isPressed.value, IOSpringValues.button)
);

// Interpolate animation values from `isPressed` values
const pressedAnimationStyle = useAnimatedStyle(() => {
// Scale down button slightly when pressed
const scale = interpolate(
progressPressed.value,
[0, 1],
[1, animationScaleValue],
Extrapolate.CLAMP
);

return {
transform: [{ scale }]
};
});

const onPressIn = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 1;
}, [isPressed]);
const onPressOut = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 0;
}, [isPressed]);

const backgroundColor = useMemo(
() => IOColors[mapVariantStates[variant].background],
[variant]
Expand Down Expand Up @@ -201,7 +161,7 @@ export const AlertEdgeToEdge = ({
>
<Animated.View
entering={enterTransitionAlertEdgeToEdgeContent}
style={[styles.alert, pressedAnimationStyle]}
style={[styles.alert, scaleAnimatedStyle]}
>
{renderMainBlock()}
</Animated.View>
Expand Down
58 changes: 6 additions & 52 deletions src/components/banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from "react";
import React from "react";
import {
AccessibilityRole,
GestureResponderEvent,
Expand All @@ -7,28 +7,19 @@ import {
View,
ViewStyle
} from "react-native";
import Animated, {
Extrapolation,
interpolate,
SharedValue,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withSpring
} from "react-native-reanimated";
import Animated from "react-native-reanimated";
import {
IOBannerBigSpacing,
IOBannerRadius,
IOBannerSmallHSpacing,
IOBannerSmallVSpacing,
IOScaleValues,
IOSpringValues,
IOStyles,
useIOExperimentalDesign,
useIOTheme,
useIOThemeContext
} from "../../core";
import { hexToRgba, IOColors } from "../../core/IOColors";
import { useScaleAnimation } from "../../hooks";
import { WithTestID } from "../../utils/types";
import { IconButton } from "../buttons";
import {
Expand Down Expand Up @@ -159,7 +150,8 @@ export const Banner = ({
accessibilityLabel,
testID
}: Banner) => {
const isPressed: SharedValue<number> = useSharedValue(0);
const { onPressIn, onPressOut, scaleAnimatedStyle } =
useScaleAnimation("medium");

const { isExperimental } = useIOExperimentalDesign();
const { themeType } = useIOThemeContext();
Expand All @@ -181,40 +173,6 @@ export const Banner = ({
paddingHorizontal: size === "big" ? sizeBigPadding : sizeSmallHPadding
};

// Scaling transformation applied when the button is pressed
const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState;

// Using a spring-based animation for our interpolations
const progressPressed = useDerivedValue(() =>
withSpring(isPressed.value, IOSpringValues.button)
);

// Interpolate animation values from `isPressed` values
const pressedAnimationStyle = useAnimatedStyle(() => {
// Link color states to the pressed states

// Scale down button slightly when pressed
const scale = interpolate(
progressPressed.value,
[0, 1],
[1, animationScaleValue],
Extrapolation.CLAMP
);

return {
transform: [{ scale }]
};
});

const onPressIn = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 1;
}, [isPressed]);
const onPressOut = useCallback(() => {
// eslint-disable-next-line functional/immutable-data
isPressed.value = 0;
}, [isPressed]);

/* Generates a complete fallbackAccessibilityLabel by concatenating the title, content, and action
if they are present. */
const fallbackAccessibilityLabel = [title, content, action]
Expand Down Expand Up @@ -305,11 +263,7 @@ export const Banner = ({
accessible={false}
>
<Animated.View
style={[
styles.container,
dynamicContainerStyles,
pressedAnimationStyle
]}
style={[styles.container, dynamicContainerStyles, scaleAnimatedStyle]}
>
{renderMainBlock()}
</Animated.View>
Expand Down
Loading
Loading