@pagopa/io-app-design-system 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/lib/commonjs/components/alert/Alert.js +10 -31
  2. package/lib/commonjs/components/alert/Alert.js.map +1 -1
  3. package/lib/commonjs/components/alert/AlertEdgeToEdge.js +9 -29
  4. package/lib/commonjs/components/alert/AlertEdgeToEdge.js.map +1 -1
  5. package/lib/commonjs/components/banner/Banner.js +10 -34
  6. package/lib/commonjs/components/banner/Banner.js.map +1 -1
  7. package/lib/commonjs/components/buttons/ButtonLink.js +20 -53
  8. package/lib/commonjs/components/buttons/ButtonLink.js.map +1 -1
  9. package/lib/commonjs/components/buttons/ButtonOutline.js +24 -44
  10. package/lib/commonjs/components/buttons/ButtonOutline.js.map +1 -1
  11. package/lib/commonjs/components/buttons/ButtonSolid.js +14 -39
  12. package/lib/commonjs/components/buttons/ButtonSolid.js.map +1 -1
  13. package/lib/commonjs/components/buttons/IconButton.js +13 -32
  14. package/lib/commonjs/components/buttons/IconButton.js.map +1 -1
  15. package/lib/commonjs/components/buttons/IconButtonContained.js +19 -42
  16. package/lib/commonjs/components/buttons/IconButtonContained.js.map +1 -1
  17. package/lib/commonjs/components/buttons/IconButtonSolid.js +15 -31
  18. package/lib/commonjs/components/buttons/IconButtonSolid.js.map +1 -1
  19. package/lib/commonjs/components/buttons/__test__/__snapshots__/button.test.tsx.snap +34 -10
  20. package/lib/commonjs/components/layout/index.js +0 -11
  21. package/lib/commonjs/components/layout/index.js.map +1 -1
  22. package/lib/commonjs/components/listitems/ListItemAction.js +14 -40
  23. package/lib/commonjs/components/listitems/ListItemAction.js.map +1 -1
  24. package/lib/commonjs/components/listitems/ListItemCheckbox.js +13 -41
  25. package/lib/commonjs/components/listitems/ListItemCheckbox.js.map +1 -1
  26. package/lib/commonjs/components/listitems/ListItemHeader.js +2 -2
  27. package/lib/commonjs/components/listitems/ListItemHeader.js.map +1 -1
  28. package/lib/commonjs/components/listitems/ListItemInfoCopy.js +15 -43
  29. package/lib/commonjs/components/listitems/ListItemInfoCopy.js.map +1 -1
  30. package/lib/commonjs/components/listitems/ListItemNav.js +17 -48
  31. package/lib/commonjs/components/listitems/ListItemNav.js.map +1 -1
  32. package/lib/commonjs/components/listitems/ListItemNavAlert.js +19 -50
  33. package/lib/commonjs/components/listitems/ListItemNavAlert.js.map +1 -1
  34. package/lib/commonjs/components/listitems/ListItemRadio.js +20 -50
  35. package/lib/commonjs/components/listitems/ListItemRadio.js.map +1 -1
  36. package/lib/commonjs/components/listitems/ListItemRadioWithAmount.js +2 -2
  37. package/lib/commonjs/components/listitems/ListItemRadioWithAmount.js.map +1 -1
  38. package/lib/commonjs/components/listitems/ListItemTransaction.js +2 -2
  39. package/lib/commonjs/components/listitems/ListItemTransaction.js.map +1 -1
  40. package/lib/commonjs/components/listitems/{PressableListItemsBase.js → PressableListItemBase.js} +7 -7
  41. package/lib/commonjs/components/listitems/PressableListItemBase.js.map +1 -0
  42. package/lib/commonjs/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +13 -7
  43. package/lib/commonjs/components/listitems/__test__/listitem.test.js +3 -3
  44. package/lib/commonjs/components/listitems/__test__/listitem.test.js.map +1 -1
  45. package/lib/commonjs/components/listitems/index.js +11 -11
  46. package/lib/commonjs/components/listitems/index.js.map +1 -1
  47. package/lib/commonjs/components/modules/PressableModuleBase.js +17 -11
  48. package/lib/commonjs/components/modules/PressableModuleBase.js.map +1 -1
  49. package/lib/commonjs/components/modules/index.js +8 -8
  50. package/lib/commonjs/components/modules/index.js.map +1 -1
  51. package/lib/commonjs/components/numberpad/NumberButton.js +12 -28
  52. package/lib/commonjs/components/numberpad/NumberButton.js.map +1 -1
  53. package/lib/commonjs/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +20 -0
  54. package/lib/commonjs/components/tabs/TabItem.js +15 -21
  55. package/lib/commonjs/components/tabs/TabItem.js.map +1 -1
  56. package/lib/commonjs/core/IOAnimations.js +6 -12
  57. package/lib/commonjs/core/IOAnimations.js.map +1 -1
  58. package/lib/commonjs/hooks/index.js +28 -0
  59. package/lib/commonjs/hooks/index.js.map +1 -0
  60. package/lib/commonjs/hooks/useListItemAnimation.js +40 -0
  61. package/lib/commonjs/hooks/useListItemAnimation.js.map +1 -0
  62. package/lib/commonjs/hooks/useScaleAnimation.js +36 -0
  63. package/lib/commonjs/hooks/useScaleAnimation.js.map +1 -0
  64. package/lib/commonjs/index.js +11 -0
  65. package/lib/commonjs/index.js.map +1 -1
  66. package/lib/commonjs/utils/hooks/index.js +28 -0
  67. package/lib/commonjs/utils/hooks/index.js.map +1 -0
  68. package/lib/commonjs/utils/hooks/useSpringPressProgressValue.js +5 -7
  69. package/lib/commonjs/utils/hooks/useSpringPressProgressValue.js.map +1 -1
  70. package/lib/module/components/alert/Alert.js +10 -32
  71. package/lib/module/components/alert/Alert.js.map +1 -1
  72. package/lib/module/components/alert/AlertEdgeToEdge.js +10 -31
  73. package/lib/module/components/alert/AlertEdgeToEdge.js.map +1 -1
  74. package/lib/module/components/banner/Banner.js +10 -33
  75. package/lib/module/components/banner/Banner.js.map +1 -1
  76. package/lib/module/components/buttons/ButtonLink.js +23 -56
  77. package/lib/module/components/buttons/ButtonLink.js.map +1 -1
  78. package/lib/module/components/buttons/ButtonOutline.js +27 -47
  79. package/lib/module/components/buttons/ButtonOutline.js.map +1 -1
  80. package/lib/module/components/buttons/ButtonSolid.js +17 -42
  81. package/lib/module/components/buttons/ButtonSolid.js.map +1 -1
  82. package/lib/module/components/buttons/IconButton.js +16 -35
  83. package/lib/module/components/buttons/IconButton.js.map +1 -1
  84. package/lib/module/components/buttons/IconButtonContained.js +21 -45
  85. package/lib/module/components/buttons/IconButtonContained.js.map +1 -1
  86. package/lib/module/components/buttons/IconButtonSolid.js +17 -34
  87. package/lib/module/components/buttons/IconButtonSolid.js.map +1 -1
  88. package/lib/module/components/buttons/__test__/__snapshots__/button.test.tsx.snap +34 -10
  89. package/lib/module/components/layout/index.js +0 -1
  90. package/lib/module/components/layout/index.js.map +1 -1
  91. package/lib/module/components/listitems/ListItemAction.js +15 -42
  92. package/lib/module/components/listitems/ListItemAction.js.map +1 -1
  93. package/lib/module/components/listitems/ListItemCheckbox.js +15 -43
  94. package/lib/module/components/listitems/ListItemCheckbox.js.map +1 -1
  95. package/lib/module/components/listitems/ListItemHeader.js +2 -2
  96. package/lib/module/components/listitems/ListItemHeader.js.map +1 -1
  97. package/lib/module/components/listitems/ListItemInfoCopy.js +16 -45
  98. package/lib/module/components/listitems/ListItemInfoCopy.js.map +1 -1
  99. package/lib/module/components/listitems/ListItemNav.js +17 -47
  100. package/lib/module/components/listitems/ListItemNav.js.map +1 -1
  101. package/lib/module/components/listitems/ListItemNavAlert.js +19 -49
  102. package/lib/module/components/listitems/ListItemNavAlert.js.map +1 -1
  103. package/lib/module/components/listitems/ListItemRadio.js +22 -52
  104. package/lib/module/components/listitems/ListItemRadio.js.map +1 -1
  105. package/lib/module/components/listitems/ListItemRadioWithAmount.js +1 -1
  106. package/lib/module/components/listitems/ListItemRadioWithAmount.js.map +1 -1
  107. package/lib/module/components/listitems/ListItemTransaction.js +1 -1
  108. package/lib/module/components/listitems/ListItemTransaction.js.map +1 -1
  109. package/lib/module/components/listitems/{PressableListItemsBase.js → PressableListItemBase.js} +7 -7
  110. package/lib/module/components/listitems/PressableListItemBase.js.map +1 -0
  111. package/lib/module/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +13 -7
  112. package/lib/module/components/listitems/__test__/listitem.test.js +1 -1
  113. package/lib/module/components/listitems/__test__/listitem.test.js.map +1 -1
  114. package/lib/module/components/listitems/index.js +1 -1
  115. package/lib/module/components/listitems/index.js.map +1 -1
  116. package/lib/module/components/modules/PressableModuleBase.js +17 -10
  117. package/lib/module/components/modules/PressableModuleBase.js.map +1 -1
  118. package/lib/module/components/modules/index.js +1 -1
  119. package/lib/module/components/modules/index.js.map +1 -1
  120. package/lib/module/components/numberpad/NumberButton.js +14 -30
  121. package/lib/module/components/numberpad/NumberButton.js.map +1 -1
  122. package/lib/module/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +20 -0
  123. package/lib/module/components/tabs/TabItem.js +18 -24
  124. package/lib/module/components/tabs/TabItem.js.map +1 -1
  125. package/lib/module/core/IOAnimations.js +4 -10
  126. package/lib/module/core/IOAnimations.js.map +1 -1
  127. package/lib/module/hooks/index.js +3 -0
  128. package/lib/module/hooks/index.js.map +1 -0
  129. package/lib/module/hooks/useListItemAnimation.js +33 -0
  130. package/lib/module/hooks/useListItemAnimation.js.map +1 -0
  131. package/lib/module/hooks/useScaleAnimation.js +29 -0
  132. package/lib/module/hooks/useScaleAnimation.js.map +1 -0
  133. package/lib/module/index.js +1 -0
  134. package/lib/module/index.js.map +1 -1
  135. package/lib/module/utils/hooks/index.js +3 -0
  136. package/lib/module/utils/hooks/index.js.map +1 -0
  137. package/lib/module/utils/hooks/useSpringPressProgressValue.js +5 -5
  138. package/lib/module/utils/hooks/useSpringPressProgressValue.js.map +1 -1
  139. package/lib/typescript/components/alert/Alert.d.ts.map +1 -1
  140. package/lib/typescript/components/alert/AlertEdgeToEdge.d.ts.map +1 -1
  141. package/lib/typescript/components/banner/Banner.d.ts.map +1 -1
  142. package/lib/typescript/components/buttons/ButtonLink.d.ts.map +1 -1
  143. package/lib/typescript/components/buttons/ButtonOutline.d.ts.map +1 -1
  144. package/lib/typescript/components/buttons/ButtonSolid.d.ts.map +1 -1
  145. package/lib/typescript/components/buttons/IconButton.d.ts.map +1 -1
  146. package/lib/typescript/components/buttons/IconButtonContained.d.ts.map +1 -1
  147. package/lib/typescript/components/buttons/IconButtonSolid.d.ts.map +1 -1
  148. package/lib/typescript/components/layout/index.d.ts +0 -1
  149. package/lib/typescript/components/layout/index.d.ts.map +1 -1
  150. package/lib/typescript/components/listitems/ListItemAction.d.ts.map +1 -1
  151. package/lib/typescript/components/listitems/ListItemCheckbox.d.ts.map +1 -1
  152. package/lib/typescript/components/listitems/ListItemInfoCopy.d.ts.map +1 -1
  153. package/lib/typescript/components/listitems/ListItemNav.d.ts.map +1 -1
  154. package/lib/typescript/components/listitems/ListItemNavAlert.d.ts.map +1 -1
  155. package/lib/typescript/components/listitems/ListItemRadio.d.ts.map +1 -1
  156. package/lib/typescript/components/listitems/ListItemRadioWithAmount.d.ts.map +1 -1
  157. package/lib/typescript/components/listitems/ListItemTransaction.d.ts +1 -1
  158. package/lib/typescript/components/listitems/ListItemTransaction.d.ts.map +1 -1
  159. package/lib/typescript/components/listitems/{PressableListItemsBase.d.ts → PressableListItemBase.d.ts} +3 -2
  160. package/lib/typescript/components/listitems/PressableListItemBase.d.ts.map +1 -0
  161. package/lib/typescript/components/listitems/index.d.ts +1 -1
  162. package/lib/typescript/components/listitems/index.d.ts.map +1 -1
  163. package/lib/typescript/components/modules/PressableModuleBase.d.ts.map +1 -1
  164. package/lib/typescript/components/modules/index.d.ts +1 -1
  165. package/lib/typescript/components/modules/index.d.ts.map +1 -1
  166. package/lib/typescript/components/numberpad/NumberButton.d.ts.map +1 -1
  167. package/lib/typescript/components/tabs/TabItem.d.ts.map +1 -1
  168. package/lib/typescript/core/IOAnimations.d.ts +6 -10
  169. package/lib/typescript/core/IOAnimations.d.ts.map +1 -1
  170. package/lib/typescript/hooks/index.d.ts +3 -0
  171. package/lib/typescript/hooks/index.d.ts.map +1 -0
  172. package/lib/typescript/hooks/useListItemAnimation.d.ts +10 -0
  173. package/lib/typescript/hooks/useListItemAnimation.d.ts.map +1 -0
  174. package/lib/typescript/hooks/useScaleAnimation.d.ts +10 -0
  175. package/lib/typescript/hooks/useScaleAnimation.d.ts.map +1 -0
  176. package/lib/typescript/index.d.ts +1 -0
  177. package/lib/typescript/index.d.ts.map +1 -1
  178. package/lib/typescript/utils/hooks/index.d.ts +3 -0
  179. package/lib/typescript/utils/hooks/index.d.ts.map +1 -0
  180. package/lib/typescript/utils/hooks/useSpringPressProgressValue.d.ts +7 -8
  181. package/lib/typescript/utils/hooks/useSpringPressProgressValue.d.ts.map +1 -1
  182. package/package.json +1 -1
  183. package/src/components/alert/Alert.tsx +7 -46
  184. package/src/components/alert/AlertEdgeToEdge.tsx +6 -46
  185. package/src/components/banner/Banner.tsx +6 -52
  186. package/src/components/buttons/ButtonLink.tsx +32 -89
  187. package/src/components/buttons/ButtonOutline.tsx +26 -60
  188. package/src/components/buttons/ButtonSolid.tsx +11 -58
  189. package/src/components/buttons/IconButton.tsx +10 -47
  190. package/src/components/buttons/IconButtonContained.tsx +21 -57
  191. package/src/components/buttons/IconButtonSolid.tsx +15 -46
  192. package/src/components/buttons/__test__/__snapshots__/button.test.tsx.snap +34 -10
  193. package/src/components/layout/index.tsx +0 -1
  194. package/src/components/listitems/ListItemAction.tsx +10 -66
  195. package/src/components/listitems/ListItemCheckbox.tsx +10 -68
  196. package/src/components/listitems/ListItemHeader.tsx +2 -2
  197. package/src/components/listitems/ListItemInfoCopy.tsx +11 -71
  198. package/src/components/listitems/ListItemNav.tsx +13 -74
  199. package/src/components/listitems/ListItemNavAlert.tsx +18 -92
  200. package/src/components/listitems/ListItemRadio.tsx +14 -75
  201. package/src/components/listitems/ListItemRadioWithAmount.tsx +2 -1
  202. package/src/components/listitems/ListItemTransaction.tsx +1 -1
  203. package/src/components/listitems/{PressableListItemsBase.tsx → PressableListItemBase.tsx} +7 -6
  204. package/src/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +13 -7
  205. package/src/components/listitems/__test__/listitem.test.tsx +1 -1
  206. package/src/components/listitems/index.tsx +1 -1
  207. package/src/components/modules/PressableModuleBase.tsx +15 -8
  208. package/src/components/modules/index.tsx +1 -1
  209. package/src/components/numberpad/NumberButton.tsx +12 -43
  210. package/src/components/numberpad/__test__/__snapshots__/NumberPad.test.tsx.snap +20 -0
  211. package/src/components/tabs/TabItem.tsx +15 -29
  212. package/src/core/IOAnimations.ts +8 -10
  213. package/src/hooks/index.tsx +2 -0
  214. package/src/hooks/useListItemAnimation.tsx +59 -0
  215. package/src/hooks/useScaleAnimation.tsx +41 -0
  216. package/src/index.tsx +1 -0
  217. package/src/utils/hooks/index.tsx +2 -0
  218. package/src/utils/hooks/useSpringPressProgressValue.ts +14 -8
  219. package/lib/commonjs/components/layout/FooterWithButtons.js +0 -84
  220. package/lib/commonjs/components/layout/FooterWithButtons.js.map +0 -1
  221. package/lib/commonjs/components/listitems/PressableListItemsBase.js.map +0 -1
  222. package/lib/commonjs/components/listitems/hooks/useListItemSpringAnimation.js +0 -56
  223. package/lib/commonjs/components/listitems/hooks/useListItemSpringAnimation.js.map +0 -1
  224. package/lib/commonjs/components/modules/hooks/useModuleSpringAnimation.js +0 -41
  225. package/lib/commonjs/components/modules/hooks/useModuleSpringAnimation.js.map +0 -1
  226. package/lib/module/components/layout/FooterWithButtons.js +0 -75
  227. package/lib/module/components/layout/FooterWithButtons.js.map +0 -1
  228. package/lib/module/components/listitems/PressableListItemsBase.js.map +0 -1
  229. package/lib/module/components/listitems/hooks/useListItemSpringAnimation.js +0 -47
  230. package/lib/module/components/listitems/hooks/useListItemSpringAnimation.js.map +0 -1
  231. package/lib/module/components/modules/hooks/useModuleSpringAnimation.js +0 -34
  232. package/lib/module/components/modules/hooks/useModuleSpringAnimation.js.map +0 -1
  233. package/lib/typescript/components/layout/FooterWithButtons.d.ts +0 -16
  234. package/lib/typescript/components/layout/FooterWithButtons.d.ts.map +0 -1
  235. package/lib/typescript/components/listitems/PressableListItemsBase.d.ts.map +0 -1
  236. package/lib/typescript/components/listitems/hooks/useListItemSpringAnimation.d.ts +0 -13
  237. package/lib/typescript/components/listitems/hooks/useListItemSpringAnimation.d.ts.map +0 -1
  238. package/lib/typescript/components/modules/hooks/useModuleSpringAnimation.d.ts +0 -10
  239. package/lib/typescript/components/modules/hooks/useModuleSpringAnimation.d.ts.map +0 -1
  240. package/src/components/layout/FooterWithButtons.tsx +0 -90
  241. package/src/components/listitems/hooks/useListItemSpringAnimation.ts +0 -72
  242. package/src/components/modules/hooks/useModuleSpringAnimation.ts +0 -49
@@ -1,4 +1,4 @@
1
- import React, { ComponentProps, useCallback, useEffect, useRef } from "react";
1
+ import React, { ComponentProps, useCallback } from "react";
2
2
  import {
3
3
  GestureResponderEvent,
4
4
  Pressable,
@@ -7,25 +7,20 @@ import {
7
7
  } from "react-native";
8
8
  import ReactNativeHapticFeedback from "react-native-haptic-feedback";
9
9
  import Animated, {
10
- Extrapolate,
11
- interpolate,
12
10
  interpolateColor,
13
11
  useAnimatedStyle,
14
- useDerivedValue,
15
- useSharedValue,
16
- withSpring
12
+ useReducedMotion
17
13
  } from "react-native-reanimated";
18
14
  import {
19
15
  IOButtonLegacyStyles,
20
16
  IOButtonStyles,
21
17
  IOColors,
22
- IOScaleValues,
23
- IOSpringValues,
24
18
  enterTransitionInnerContent,
25
19
  enterTransitionInnerContentSmall,
26
20
  exitTransitionInnerContent,
27
21
  useIOExperimentalDesign
28
22
  } from "../../core";
23
+ import { useScaleAnimation } from "../../hooks";
29
24
  import { WithTestID } from "../../utils/types";
30
25
  import { IOIconSizeScale, IOIcons, Icon } from "../icons";
31
26
  import { LoadingSpinner } from "../loadingSpinner";
@@ -176,21 +171,10 @@ export const ButtonSolid = React.forwardRef<View, ButtonSolidProps>(
176
171
  },
177
172
  ref
178
173
  ) => {
179
- const isPressed = useSharedValue(0);
180
174
  const { isExperimental } = useIOExperimentalDesign();
181
- // Scaling transformation applied when the button is pressed
182
- const animationScaleValue = IOScaleValues?.basicButton?.pressedState;
183
-
184
- /* Prevent the component from triggering the `isEntering' transition
185
- on the on the first render. Solution from this discussion:
186
- https://github.com/software-mansion/react-native-reanimated/discussions/2513
187
- */
188
- const isMounted = useRef(false);
189
-
190
- useEffect(() => {
191
- // eslint-disable-next-line functional/immutable-data
192
- isMounted.current = true;
193
- }, []);
175
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
176
+ useScaleAnimation();
177
+ const reducedMotion = useReducedMotion();
194
178
 
195
179
  const colorMap = React.useMemo(
196
180
  () => (isExperimental ? mapColorStates : mapLegacyColorStates),
@@ -202,43 +186,18 @@ export const ButtonSolid = React.forwardRef<View, ButtonSolidProps>(
202
186
  [isExperimental]
203
187
  );
204
188
 
205
- // Using a spring-based animation for our interpolations
206
- const progressPressed = useDerivedValue(() =>
207
- withSpring(isPressed.value, IOSpringValues.button)
208
- );
209
-
210
189
  // Interpolate animation values from `isPressed` values
211
190
  const pressedAnimationStyle = useAnimatedStyle(() => {
212
191
  // Link color states to the pressed states
213
192
  const backgroundColor = interpolateColor(
214
- progressPressed.value,
193
+ progress.value,
215
194
  [0, 1],
216
195
  [colorMap[color].default, colorMap[color].pressed]
217
196
  );
218
197
 
219
- // Scale down button slightly when pressed
220
- const scale = interpolate(
221
- progressPressed.value,
222
- [0, 1],
223
- [1, animationScaleValue],
224
- Extrapolate.CLAMP
225
- );
226
-
227
- return {
228
- backgroundColor,
229
- transform: [{ scale }]
230
- };
198
+ return { backgroundColor };
231
199
  });
232
200
 
233
- const onPressIn = useCallback(() => {
234
- // eslint-disable-next-line functional/immutable-data
235
- isPressed.value = 1;
236
- }, [isPressed]);
237
- const onPressOut = useCallback(() => {
238
- // eslint-disable-next-line functional/immutable-data
239
- isPressed.value = 0;
240
- }, [isPressed]);
241
-
242
201
  const handleOnPress = useCallback(
243
202
  (event: GestureResponderEvent) => {
244
203
  /* Don't call `onPress` if the button is
@@ -289,15 +248,14 @@ export const ButtonSolid = React.forwardRef<View, ButtonSolidProps>(
289
248
  : { backgroundColor: colorMap[color]?.default },
290
249
  /* Prevent Reanimated from overriding background colors
291
250
  if button is disabled */
251
+ !disabled && !reducedMotion && scaleAnimatedStyle,
292
252
  !disabled && pressedAnimationStyle
293
253
  ]}
294
254
  >
295
255
  {loading && (
296
256
  <Animated.View
297
257
  style={buttonStyles.buttonInner}
298
- entering={
299
- isMounted.current ? enterTransitionInnerContentSmall : undefined
300
- }
258
+ entering={enterTransitionInnerContentSmall}
301
259
  exiting={exitTransitionInnerContent}
302
260
  >
303
261
  <LoadingSpinner color={foregroundColor} />
@@ -310,12 +268,7 @@ export const ButtonSolid = React.forwardRef<View, ButtonSolidProps>(
310
268
  buttonStyles.buttonInner,
311
269
  iconPosition === "end" && { flexDirection: "row-reverse" }
312
270
  ]}
313
- entering={
314
- isMounted.current ? enterTransitionInnerContent : undefined
315
- }
316
- /* Temporarily disable the exiting transition because it caused
317
- a weird glitch on page exit */
318
- // exiting={exitTransitionInnerContent}
271
+ entering={enterTransitionInnerContent}
319
272
  >
320
273
  {icon && (
321
274
  <>
@@ -1,24 +1,18 @@
1
- import React, { useCallback, useMemo } from "react";
1
+ import React, { useMemo } from "react";
2
2
  import { GestureResponderEvent, Pressable } from "react-native";
3
3
  import Animated, {
4
- Extrapolate,
5
- interpolate,
6
4
  interpolateColor,
7
5
  useAnimatedProps,
8
- useAnimatedStyle,
9
- useDerivedValue,
10
- useSharedValue,
11
- withSpring
6
+ useReducedMotion
12
7
  } from "react-native-reanimated";
13
8
  import {
14
9
  IOColors,
15
10
  IOIconButtonStyles,
16
- IOScaleValues,
17
- IOSpringValues,
18
11
  IOStyles,
19
12
  hexToRgba,
20
13
  useIOExperimentalDesign
21
14
  } from "../../core";
15
+ import { useScaleAnimation } from "../../hooks";
22
16
  import { WithTestID } from "../../utils/types";
23
17
  import {
24
18
  AnimatedIcon,
@@ -116,7 +110,9 @@ export const IconButton = ({
116
110
  accessibilityHint,
117
111
  testID
118
112
  }: IconButton) => {
119
- const isPressed = useSharedValue(0);
113
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
114
+ useScaleAnimation("exaggerated");
115
+ const reducedMotion = useReducedMotion();
120
116
 
121
117
  const { isExperimental } = useIOExperimentalDesign();
122
118
 
@@ -125,56 +121,23 @@ export const IconButton = ({
125
121
  [isExperimental]
126
122
  );
127
123
 
128
- // Scaling transformation applied when the button is pressed
129
- const animationScaleValue = IOScaleValues?.exaggeratedButton?.pressedState;
130
-
131
- // Using a spring-based animation for our interpolations
132
- const progressPressed = useDerivedValue(() =>
133
- withSpring(isPressed.value, IOSpringValues.button)
134
- );
135
-
136
- // Interpolate animation values from `isPressed` values
137
-
138
- const pressedAnimationStyle = useAnimatedStyle(() => {
139
- // Scale down button slightly when pressed
140
- const scale = interpolate(
141
- progressPressed.value,
142
- [0, 1],
143
- [1, animationScaleValue],
144
- Extrapolate.CLAMP
145
- );
146
-
147
- return {
148
- transform: [{ scale }]
149
- };
150
- });
151
-
152
124
  // Animate the <Icon> color prop
153
125
  const animatedColor = useAnimatedProps(() => {
154
126
  const iconColor = interpolateColor(
155
- progressPressed.value,
127
+ progress.value,
156
128
  [0, 1],
157
129
  [colorMap[color].icon.default, colorMap[color].icon.pressed]
158
130
  );
159
131
  return { color: iconColor };
160
132
  });
161
133
 
162
- const handlePressIn = useCallback(() => {
163
- // eslint-disable-next-line functional/immutable-data
164
- isPressed.value = 1;
165
- }, [isPressed]);
166
- const handlePressOut = useCallback(() => {
167
- // eslint-disable-next-line functional/immutable-data
168
- isPressed.value = 0;
169
- }, [isPressed]);
170
-
171
134
  return (
172
135
  <Pressable
173
136
  disabled={disabled}
174
137
  // Events
175
138
  onPress={onPress}
176
- onPressIn={handlePressIn}
177
- onPressOut={handlePressOut}
139
+ onPressIn={onPressIn}
140
+ onPressOut={onPressOut}
178
141
  // Accessibility
179
142
  accessible={true}
180
143
  accessibilityRole={"button"}
@@ -192,7 +155,7 @@ export const IconButton = ({
192
155
  IOIconButtonStyles.buttonSizeSmall,
193
156
  IOStyles.alignCenter,
194
157
  IOStyles.centerJustified,
195
- !disabled && pressedAnimationStyle
158
+ !disabled && !reducedMotion && scaleAnimatedStyle
196
159
  ]}
197
160
  >
198
161
  {!disabled ? (
@@ -1,15 +1,10 @@
1
1
  import * as React from "react";
2
- import { useCallback } from "react";
3
2
  import { GestureResponderEvent, Pressable } from "react-native";
4
3
  import Animated, {
5
- Extrapolate,
6
- interpolate,
7
4
  interpolateColor,
8
5
  useAnimatedProps,
9
6
  useAnimatedStyle,
10
- useDerivedValue,
11
- useSharedValue,
12
- withSpring
7
+ useReducedMotion
13
8
  } from "react-native-reanimated";
14
9
  import {
15
10
  AnimatedIcon,
@@ -20,11 +15,10 @@ import {
20
15
  IOButtonStyles,
21
16
  IOColors,
22
17
  IOIconButtonStyles,
23
- IOScaleValues,
24
- IOSpringValues,
25
18
  hexToRgba,
26
19
  useIOExperimentalDesign
27
20
  } from "../../core";
21
+ import { useScaleAnimation } from "../../hooks";
28
22
  import { WithTestID } from "../../utils/types";
29
23
 
30
24
  export type IconButtonContained = WithTestID<{
@@ -151,64 +145,33 @@ export const IconButtonContained = ({
151
145
  accessibilityHint,
152
146
  testID
153
147
  }: IconButtonContained) => {
154
- const isPressed = useSharedValue(0);
155
148
  const { isExperimental } = useIOExperimentalDesign();
156
149
 
150
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
151
+ useScaleAnimation("exaggerated");
152
+ const reducedMotion = useReducedMotion();
153
+
157
154
  const colorMap = React.useMemo(
158
155
  () => (isExperimental ? mapColorStates : mapLegacyColorStates),
159
156
  [isExperimental]
160
157
  );
161
158
 
162
- // Scaling transformation applied when the button is pressed
163
- const animationScaleValue = IOScaleValues?.exaggeratedButton?.pressedState;
164
-
165
- // Using a spring-based animation for our interpolations
166
- const progressPressed = useDerivedValue(() =>
167
- withSpring(isPressed.value, IOSpringValues.button)
168
- );
169
-
170
- // Interpolate animation values from `isPressed` values
171
-
172
- const pressedAnimationStyle = useAnimatedStyle(() => {
173
- // Link color states to the pressed states
174
- const backgroundColor = interpolateColor(
175
- progressPressed.value,
159
+ const backgroundColorAnimationStyle = useAnimatedStyle(() => ({
160
+ backgroundColor: interpolateColor(
161
+ progress.value,
176
162
  [0, 1],
177
163
  [colorMap[color].background.default, colorMap[color].background.pressed]
178
- );
179
-
180
- // Scale down button slightly when pressed
181
- const scale = interpolate(
182
- progressPressed.value,
183
- [0, 1],
184
- [1, animationScaleValue],
185
- Extrapolate.CLAMP
186
- );
187
-
188
- return {
189
- backgroundColor,
190
- transform: [{ scale }]
191
- };
192
- });
164
+ )
165
+ }));
193
166
 
194
167
  // Animate the <Icon> color prop
195
- const animatedColor = useAnimatedProps(() => {
196
- const iconColor = interpolateColor(
197
- progressPressed.value,
168
+ const iconColorAnimationStyle = useAnimatedProps(() => ({
169
+ color: interpolateColor(
170
+ progress.value,
198
171
  [0, 1],
199
172
  [colorMap[color].icon.default, colorMap[color].icon.pressed]
200
- );
201
- return { color: iconColor };
202
- });
203
-
204
- const handlePressIn = useCallback(() => {
205
- // eslint-disable-next-line functional/immutable-data
206
- isPressed.value = 1;
207
- }, [isPressed]);
208
- const handlePressOut = useCallback(() => {
209
- // eslint-disable-next-line functional/immutable-data
210
- isPressed.value = 0;
211
- }, [isPressed]);
173
+ )
174
+ }));
212
175
 
213
176
  return (
214
177
  <Pressable
@@ -218,8 +181,8 @@ export const IconButtonContained = ({
218
181
  accessibilityState={{ disabled }}
219
182
  testID={testID}
220
183
  onPress={onPress}
221
- onPressIn={handlePressIn}
222
- onPressOut={handlePressOut}
184
+ onPressIn={onPressIn}
185
+ onPressOut={onPressOut}
223
186
  accessible={true}
224
187
  disabled={disabled}
225
188
  style={IOButtonStyles.dimensionsDefault}
@@ -228,13 +191,14 @@ export const IconButtonContained = ({
228
191
  style={[
229
192
  IOIconButtonStyles.button,
230
193
  IOIconButtonStyles.buttonSizeDefault,
231
- !disabled && pressedAnimationStyle
194
+ !disabled && !reducedMotion && scaleAnimatedStyle,
195
+ !disabled && backgroundColorAnimationStyle
232
196
  ]}
233
197
  >
234
198
  {!disabled ? (
235
199
  <AnimatedIconClassComponent
236
200
  name={icon}
237
- animatedProps={animatedColor}
201
+ animatedProps={iconColorAnimationStyle}
238
202
  color={colorMap[color]?.icon?.default}
239
203
  />
240
204
  ) : (
@@ -1,23 +1,17 @@
1
1
  import * as React from "react";
2
- import { useCallback } from "react";
3
2
  import { GestureResponderEvent, Pressable } from "react-native";
4
3
  import Animated, {
5
- Extrapolate,
6
- interpolate,
7
4
  interpolateColor,
8
5
  useAnimatedStyle,
9
- useDerivedValue,
10
- useSharedValue,
11
- withSpring
6
+ useReducedMotion
12
7
  } from "react-native-reanimated";
13
8
  import {
14
9
  IOButtonStyles,
15
10
  IOIconButtonStyles,
16
- IOScaleValues,
17
- IOSpringValues,
18
11
  useIOExperimentalDesign
19
12
  } from "../../core";
20
13
  import { IOColors, hexToRgba } from "../../core/IOColors";
14
+ import { useScaleAnimation } from "../../hooks";
21
15
  import { WithTestID } from "../../utils/types";
22
16
  import { AnimatedIcon, IOIcons } from "../icons";
23
17
 
@@ -110,50 +104,24 @@ export const IconButtonSolid = ({
110
104
  accessibilityHint,
111
105
  testID
112
106
  }: IconButtonSolid) => {
113
- const isPressed = useSharedValue(0);
114
107
  const { isExperimental } = useIOExperimentalDesign();
115
- // Scaling transformation applied when the button is pressed
116
- const animationScaleValue = IOScaleValues?.exaggeratedButton?.pressedState;
117
108
 
118
- // Using a spring-based animation for our interpolations
119
- const progressPressed = useDerivedValue(() =>
120
- withSpring(isPressed.value, IOSpringValues.button)
121
- );
109
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
110
+ useScaleAnimation("exaggerated");
111
+ const reducedMotion = useReducedMotion();
122
112
 
123
113
  const colorMap = React.useMemo(
124
114
  () => (isExperimental ? mapColorStates : mapLegacyColorStates),
125
115
  [isExperimental]
126
116
  );
127
- // Interpolate animation values from `isPressed` values
128
- const pressedAnimationStyle = useAnimatedStyle(() => {
129
- const backgroundColor = interpolateColor(
130
- progressPressed.value,
131
- [0, 1],
132
- [colorMap[color].background.default, colorMap[color].background.pressed]
133
- );
134
117
 
135
- // Scale down button slightly when pressed
136
- const scale = interpolate(
137
- progressPressed.value,
118
+ const backgroundColorAnimationStyle = useAnimatedStyle(() => ({
119
+ backgroundColor: interpolateColor(
120
+ progress.value,
138
121
  [0, 1],
139
- [1, animationScaleValue],
140
- Extrapolate.CLAMP
141
- );
142
-
143
- return {
144
- backgroundColor,
145
- transform: [{ scale }]
146
- };
147
- });
148
-
149
- const handlePressIn = useCallback(() => {
150
- // eslint-disable-next-line functional/immutable-data
151
- isPressed.value = 1;
152
- }, [isPressed]);
153
- const handlePressOut = useCallback(() => {
154
- // eslint-disable-next-line functional/immutable-data
155
- isPressed.value = 0;
156
- }, [isPressed]);
122
+ [colorMap[color].background.default, colorMap[color].background.pressed]
123
+ )
124
+ }));
157
125
 
158
126
  return (
159
127
  <Pressable
@@ -163,8 +131,8 @@ export const IconButtonSolid = ({
163
131
  accessibilityState={{ disabled }}
164
132
  testID={testID}
165
133
  onPress={onPress}
166
- onPressIn={handlePressIn}
167
- onPressOut={handlePressOut}
134
+ onPressIn={onPressIn}
135
+ onPressOut={onPressOut}
168
136
  accessible={true}
169
137
  disabled={disabled}
170
138
  style={IOButtonStyles.dimensionsDefault}
@@ -173,7 +141,8 @@ export const IconButtonSolid = ({
173
141
  style={[
174
142
  IOIconButtonStyles.button,
175
143
  IOIconButtonStyles.buttonSizeLarge,
176
- !disabled && pressedAnimationStyle,
144
+ !disabled && !reducedMotion && scaleAnimatedStyle,
145
+ !disabled && backgroundColorAnimationStyle,
177
146
  disabled
178
147
  ? {
179
148
  backgroundColor: colorMap[color]?.background?.disabled
@@ -59,6 +59,9 @@ exports[`Test Buttons Components - Experimental Enabled ButtonLink Snapshot 1`]
59
59
  "textAlignVertical": "center",
60
60
  },
61
61
  false,
62
+ {
63
+ "columnGap": 8,
64
+ },
62
65
  {},
63
66
  {
64
67
  "transform": [
@@ -166,14 +169,16 @@ exports[`Test Buttons Components - Experimental Enabled ButtonOutline Snapshot 1
166
169
  "borderColor": "#0B3EE3",
167
170
  },
168
171
  {
169
- "backgroundColor": undefined,
170
- "borderColor": undefined,
171
172
  "transform": [
172
173
  {
173
174
  "scale": undefined,
174
175
  },
175
176
  ],
176
177
  },
178
+ {
179
+ "backgroundColor": undefined,
180
+ "borderColor": undefined,
181
+ },
177
182
  ]
178
183
  }
179
184
  >
@@ -276,17 +281,20 @@ exports[`Test Buttons Components - Experimental Enabled ButtonSolid Snapshot 1`]
276
281
  "backgroundColor": "#0B3EE3",
277
282
  },
278
283
  {
279
- "backgroundColor": undefined,
280
284
  "transform": [
281
285
  {
282
286
  "scale": undefined,
283
287
  },
284
288
  ],
285
289
  },
290
+ {
291
+ "backgroundColor": undefined,
292
+ },
286
293
  ]
287
294
  }
288
295
  >
289
296
  <View
297
+ entering={[Function]}
290
298
  style={
291
299
  [
292
300
  {
@@ -510,13 +518,15 @@ exports[`Test Buttons Components - Experimental Enabled IconButtonContained Snap
510
518
  "width": 48,
511
519
  },
512
520
  {
513
- "backgroundColor": undefined,
514
521
  "transform": [
515
522
  {
516
523
  "scale": undefined,
517
524
  },
518
525
  ],
519
526
  },
527
+ {
528
+ "backgroundColor": undefined,
529
+ },
520
530
  ]
521
531
  }
522
532
  >
@@ -642,13 +652,15 @@ exports[`Test Buttons Components - Experimental Enabled IconButtonSolid Snapshot
642
652
  "width": 56,
643
653
  },
644
654
  {
645
- "backgroundColor": undefined,
646
655
  "transform": [
647
656
  {
648
657
  "scale": undefined,
649
658
  },
650
659
  ],
651
660
  },
661
+ {
662
+ "backgroundColor": undefined,
663
+ },
652
664
  {
653
665
  "backgroundColor": "#0B3EE3",
654
666
  },
@@ -778,6 +790,9 @@ exports[`Test Buttons Components ButtonLink Snapshot 1`] = `
778
790
  "textAlignVertical": "center",
779
791
  },
780
792
  false,
793
+ {
794
+ "columnGap": 8,
795
+ },
781
796
  {},
782
797
  {
783
798
  "transform": [
@@ -884,14 +899,16 @@ exports[`Test Buttons Components ButtonOutline Snapshot 1`] = `
884
899
  "borderColor": "#0073E6",
885
900
  },
886
901
  {
887
- "backgroundColor": undefined,
888
- "borderColor": undefined,
889
902
  "transform": [
890
903
  {
891
904
  "scale": undefined,
892
905
  },
893
906
  ],
894
907
  },
908
+ {
909
+ "backgroundColor": undefined,
910
+ "borderColor": undefined,
911
+ },
895
912
  ]
896
913
  }
897
914
  >
@@ -993,17 +1010,20 @@ exports[`Test Buttons Components ButtonSolid Snapshot 1`] = `
993
1010
  "backgroundColor": "#0073E6",
994
1011
  },
995
1012
  {
996
- "backgroundColor": undefined,
997
1013
  "transform": [
998
1014
  {
999
1015
  "scale": undefined,
1000
1016
  },
1001
1017
  ],
1002
1018
  },
1019
+ {
1020
+ "backgroundColor": undefined,
1021
+ },
1003
1022
  ]
1004
1023
  }
1005
1024
  >
1006
1025
  <View
1026
+ entering={[Function]}
1007
1027
  style={
1008
1028
  [
1009
1029
  {
@@ -1227,13 +1247,15 @@ exports[`Test Buttons Components IconButtonContained Snapshot 1`] = `
1227
1247
  "width": 48,
1228
1248
  },
1229
1249
  {
1230
- "backgroundColor": undefined,
1231
1250
  "transform": [
1232
1251
  {
1233
1252
  "scale": undefined,
1234
1253
  },
1235
1254
  ],
1236
1255
  },
1256
+ {
1257
+ "backgroundColor": undefined,
1258
+ },
1237
1259
  ]
1238
1260
  }
1239
1261
  >
@@ -1359,13 +1381,15 @@ exports[`Test Buttons Components IconButtonSolid Snapshot 1`] = `
1359
1381
  "width": 56,
1360
1382
  },
1361
1383
  {
1362
- "backgroundColor": undefined,
1363
1384
  "transform": [
1364
1385
  {
1365
1386
  "scale": undefined,
1366
1387
  },
1367
1388
  ],
1368
1389
  },
1390
+ {
1391
+ "backgroundColor": undefined,
1392
+ },
1369
1393
  {
1370
1394
  "backgroundColor": "#0073E6",
1371
1395
  },
@@ -1,6 +1,5 @@
1
1
  export * from "./FooterActions";
2
2
  export * from "./FooterActionsInline";
3
- export * from "./FooterWithButtons";
4
3
  export * from "./ForceScrollDownView";
5
4
  export * from "./GradientBottomActions";
6
5
  export * from "./GradientScrollView";