@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/io-app-design-system",
3
- "version": "4.2.1",
3
+ "version": "4.3.0",
4
4
  "description": "The library defining the core components of the design system of @pagopa/io-app",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useState } from "react";
1
+ import React, { forwardRef, useCallback, useState } from "react";
2
2
  import {
3
3
  ColorValue,
4
4
  GestureResponderEvent,
@@ -9,20 +9,12 @@ import {
9
9
  TextLayoutEventData,
10
10
  View
11
11
  } from "react-native";
12
- import Animated, {
13
- Extrapolation,
14
- SharedValue,
15
- interpolate,
16
- useAnimatedStyle,
17
- useDerivedValue,
18
- useSharedValue,
19
- withSpring
20
- } from "react-native-reanimated";
12
+ import Animated from "react-native-reanimated";
21
13
  import { IOVisualCostants, useIOThemeContext } from "../../core";
22
- import { IOScaleValues, IOSpringValues } from "../../core/IOAnimations";
23
14
  import { IOColors, hexToRgba } from "../../core/IOColors";
24
15
  import { IOAlertRadius } from "../../core/IOShapes";
25
16
  import { IOAlertSpacing } from "../../core/IOSpacing";
17
+ import { useScaleAnimation } from "../../hooks";
26
18
  import { WithTestID } from "../../utils/types";
27
19
  import { IOIconSizeScale, IOIcons, Icon } from "../icons";
28
20
  import { VSpacer } from "../spacer";
@@ -132,7 +124,7 @@ const mapVariantStatesDarkMode: Record<
132
124
  }
133
125
  };
134
126
 
135
- export const Alert = React.forwardRef<View, AlertType>(
127
+ export const Alert = forwardRef<View, AlertType>(
136
128
  (
137
129
  {
138
130
  variant,
@@ -146,8 +138,9 @@ export const Alert = React.forwardRef<View, AlertType>(
146
138
  }: AlertType,
147
139
  viewRef
148
140
  ): JSX.Element => {
141
+ const { onPressIn, onPressOut, scaleAnimatedStyle } =
142
+ useScaleAnimation("medium");
149
143
  const { themeType } = useIOThemeContext();
150
- const isPressed: SharedValue<number> = useSharedValue(0);
151
144
 
152
145
  const [isMultiline, setIsMultiline] = useState(false);
153
146
 
@@ -158,38 +151,6 @@ export const Alert = React.forwardRef<View, AlertType>(
158
151
  []
159
152
  );
160
153
 
161
- // Scaling transformation applied when the button is pressed
162
- const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState;
163
-
164
- // Using a spring-based animation for our interpolations
165
- const progressPressed = useDerivedValue(() =>
166
- withSpring(isPressed.value, IOSpringValues.button)
167
- );
168
-
169
- // Interpolate animation values from `isPressed` values
170
- const pressedAnimationStyle = useAnimatedStyle(() => {
171
- // Scale down button slightly when pressed
172
- const scale = interpolate(
173
- progressPressed.value,
174
- [0, 1],
175
- [1, animationScaleValue],
176
- Extrapolation.CLAMP
177
- );
178
-
179
- return {
180
- transform: [{ scale }]
181
- };
182
- });
183
-
184
- const onPressIn = useCallback(() => {
185
- // eslint-disable-next-line functional/immutable-data
186
- isPressed.value = 1;
187
- }, [isPressed]);
188
- const onPressOut = useCallback(() => {
189
- // eslint-disable-next-line functional/immutable-data
190
- isPressed.value = 0;
191
- }, [isPressed]);
192
-
193
154
  const mapVariantStates =
194
155
  themeType === "light"
195
156
  ? mapVariantStatesLightMode
@@ -287,7 +248,7 @@ export const Alert = React.forwardRef<View, AlertType>(
287
248
  fullWidth ? styles.spacingFullWidth : styles.spacingDefault,
288
249
  { backgroundColor: mapVariantStates[variant].background },
289
250
  // Disable pressed animation when component is full width
290
- !fullWidth && pressedAnimationStyle
251
+ !fullWidth && scaleAnimatedStyle
291
252
  ]}
292
253
  >
293
254
  {renderMainBlock()}
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo } from "react";
1
+ import React, { useMemo } from "react";
2
2
  import {
3
3
  GestureResponderEvent,
4
4
  Pressable,
@@ -6,18 +6,9 @@ import {
6
6
  Text,
7
7
  View
8
8
  } from "react-native";
9
- import Animated, {
10
- Extrapolate,
11
- interpolate,
12
- useAnimatedStyle,
13
- useDerivedValue,
14
- useSharedValue,
15
- withSpring
16
- } from "react-native-reanimated";
9
+ import Animated from "react-native-reanimated";
17
10
  import { useSafeAreaInsets } from "react-native-safe-area-context";
18
11
  import {
19
- IOScaleValues,
20
- IOSpringValues,
21
12
  IOVisualCostants,
22
13
  enterTransitionAlertEdgeToEdge,
23
14
  enterTransitionAlertEdgeToEdgeContent,
@@ -30,6 +21,7 @@ import {
30
21
  } from "../../core/IOColors";
31
22
  import { IOAlertSpacing } from "../../core/IOSpacing";
32
23
  import { IOStyles } from "../../core/IOStyles";
24
+ import { useScaleAnimation } from "../../hooks";
33
25
  import { makeFontStyleObject } from "../../utils/fonts";
34
26
  import { WithTestID } from "../../utils/types";
35
27
  import { IOIconSizeScale, IOIcons, Icon } from "../icons";
@@ -105,42 +97,10 @@ export const AlertEdgeToEdge = ({
105
97
  accessibilityHint,
106
98
  testID
107
99
  }: AlertEdgeToEdgeProps) => {
108
- const isPressed: Animated.SharedValue<number> = useSharedValue(0);
109
-
100
+ const { onPressIn, onPressOut, scaleAnimatedStyle } =
101
+ useScaleAnimation("slight");
110
102
  const insets = useSafeAreaInsets();
111
103
 
112
- // Scaling transformation applied when the button is pressed
113
- const animationScaleValue = IOScaleValues?.basicButton?.pressedState;
114
-
115
- // Using a spring-based animation for our interpolations
116
- const progressPressed = useDerivedValue(() =>
117
- withSpring(isPressed.value, IOSpringValues.button)
118
- );
119
-
120
- // Interpolate animation values from `isPressed` values
121
- const pressedAnimationStyle = useAnimatedStyle(() => {
122
- // Scale down button slightly when pressed
123
- const scale = interpolate(
124
- progressPressed.value,
125
- [0, 1],
126
- [1, animationScaleValue],
127
- Extrapolate.CLAMP
128
- );
129
-
130
- return {
131
- transform: [{ scale }]
132
- };
133
- });
134
-
135
- const onPressIn = useCallback(() => {
136
- // eslint-disable-next-line functional/immutable-data
137
- isPressed.value = 1;
138
- }, [isPressed]);
139
- const onPressOut = useCallback(() => {
140
- // eslint-disable-next-line functional/immutable-data
141
- isPressed.value = 0;
142
- }, [isPressed]);
143
-
144
104
  const backgroundColor = useMemo(
145
105
  () => IOColors[mapVariantStates[variant].background],
146
106
  [variant]
@@ -201,7 +161,7 @@ export const AlertEdgeToEdge = ({
201
161
  >
202
162
  <Animated.View
203
163
  entering={enterTransitionAlertEdgeToEdgeContent}
204
- style={[styles.alert, pressedAnimationStyle]}
164
+ style={[styles.alert, scaleAnimatedStyle]}
205
165
  >
206
166
  {renderMainBlock()}
207
167
  </Animated.View>
@@ -1,4 +1,4 @@
1
- import React, { useCallback } from "react";
1
+ import React from "react";
2
2
  import {
3
3
  AccessibilityRole,
4
4
  GestureResponderEvent,
@@ -7,28 +7,19 @@ import {
7
7
  View,
8
8
  ViewStyle
9
9
  } from "react-native";
10
- import Animated, {
11
- Extrapolation,
12
- interpolate,
13
- SharedValue,
14
- useAnimatedStyle,
15
- useDerivedValue,
16
- useSharedValue,
17
- withSpring
18
- } from "react-native-reanimated";
10
+ import Animated from "react-native-reanimated";
19
11
  import {
20
12
  IOBannerBigSpacing,
21
13
  IOBannerRadius,
22
14
  IOBannerSmallHSpacing,
23
15
  IOBannerSmallVSpacing,
24
- IOScaleValues,
25
- IOSpringValues,
26
16
  IOStyles,
27
17
  useIOExperimentalDesign,
28
18
  useIOTheme,
29
19
  useIOThemeContext
30
20
  } from "../../core";
31
21
  import { hexToRgba, IOColors } from "../../core/IOColors";
22
+ import { useScaleAnimation } from "../../hooks";
32
23
  import { WithTestID } from "../../utils/types";
33
24
  import { IconButton } from "../buttons";
34
25
  import {
@@ -159,7 +150,8 @@ export const Banner = ({
159
150
  accessibilityLabel,
160
151
  testID
161
152
  }: Banner) => {
162
- const isPressed: SharedValue<number> = useSharedValue(0);
153
+ const { onPressIn, onPressOut, scaleAnimatedStyle } =
154
+ useScaleAnimation("medium");
163
155
 
164
156
  const { isExperimental } = useIOExperimentalDesign();
165
157
  const { themeType } = useIOThemeContext();
@@ -181,40 +173,6 @@ export const Banner = ({
181
173
  paddingHorizontal: size === "big" ? sizeBigPadding : sizeSmallHPadding
182
174
  };
183
175
 
184
- // Scaling transformation applied when the button is pressed
185
- const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState;
186
-
187
- // Using a spring-based animation for our interpolations
188
- const progressPressed = useDerivedValue(() =>
189
- withSpring(isPressed.value, IOSpringValues.button)
190
- );
191
-
192
- // Interpolate animation values from `isPressed` values
193
- const pressedAnimationStyle = useAnimatedStyle(() => {
194
- // Link color states to the pressed states
195
-
196
- // Scale down button slightly when pressed
197
- const scale = interpolate(
198
- progressPressed.value,
199
- [0, 1],
200
- [1, animationScaleValue],
201
- Extrapolation.CLAMP
202
- );
203
-
204
- return {
205
- transform: [{ scale }]
206
- };
207
- });
208
-
209
- const onPressIn = useCallback(() => {
210
- // eslint-disable-next-line functional/immutable-data
211
- isPressed.value = 1;
212
- }, [isPressed]);
213
- const onPressOut = useCallback(() => {
214
- // eslint-disable-next-line functional/immutable-data
215
- isPressed.value = 0;
216
- }, [isPressed]);
217
-
218
176
  /* Generates a complete fallbackAccessibilityLabel by concatenating the title, content, and action
219
177
  if they are present. */
220
178
  const fallbackAccessibilityLabel = [title, content, action]
@@ -305,11 +263,7 @@ export const Banner = ({
305
263
  accessible={false}
306
264
  >
307
265
  <Animated.View
308
- style={[
309
- styles.container,
310
- dynamicContainerStyles,
311
- pressedAnimationStyle
312
- ]}
266
+ style={[styles.container, dynamicContainerStyles, scaleAnimatedStyle]}
313
267
  >
314
268
  {renderMainBlock()}
315
269
  </Animated.View>
@@ -1,23 +1,18 @@
1
- import React, { useCallback, useMemo } from "react";
1
+ import React, { forwardRef, useMemo } from "react";
2
2
  import { GestureResponderEvent, Pressable, View } from "react-native";
3
3
  import Animated, {
4
- Extrapolate,
5
- interpolate,
6
4
  interpolateColor,
7
- useAnimatedProps,
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
  IOColors,
16
- IOScaleValues,
17
- IOSpringValues,
11
+ IOSpacingScale,
18
12
  hexToRgba,
19
13
  useIOExperimentalDesign
20
14
  } from "../../core";
15
+ import { useScaleAnimation } from "../../hooks";
21
16
  import { WithTestID } from "../../utils/types";
22
17
  import {
23
18
  AnimatedIcon,
@@ -25,7 +20,6 @@ import {
25
20
  IOIcons,
26
21
  IconClassComponent
27
22
  } from "../icons";
28
- import { HSpacer } from "../spacer/Spacer";
29
23
  import { IOText, buttonTextFontSize } from "../typography";
30
24
 
31
25
  export type ColorButtonLink = "primary" | "contrast";
@@ -97,7 +91,7 @@ const mapLegacyColorStates: Record<
97
91
 
98
92
  const DISABLED_OPACITY = 0.5;
99
93
 
100
- export const ButtonLink = React.forwardRef<View, ButtonLinkProps>(
94
+ export const ButtonLink = forwardRef<View, ButtonLinkProps>(
101
95
  (
102
96
  {
103
97
  color = "primary",
@@ -112,8 +106,10 @@ export const ButtonLink = React.forwardRef<View, ButtonLinkProps>(
112
106
  },
113
107
  ref
114
108
  ) => {
115
- const isPressed = useSharedValue(0);
116
109
  const { isExperimental } = useIOExperimentalDesign();
110
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
111
+ useScaleAnimation();
112
+ const reducedMotion = useReducedMotion();
117
113
 
118
114
  const colorMap = useMemo(
119
115
  () => (isExperimental ? mapColorStates : mapLegacyColorStates),
@@ -122,70 +118,20 @@ export const ButtonLink = React.forwardRef<View, ButtonLinkProps>(
122
118
 
123
119
  const AnimatedIOText = Animated.createAnimatedComponent(IOText);
124
120
 
125
- // Scaling transformation applied when the button is pressed
126
- const animationScaleValue = IOScaleValues?.basicButton?.pressedState;
127
-
128
- // Using a spring-based animation for our interpolations
129
- const progressPressed = useDerivedValue(() =>
130
- withSpring(isPressed.value, IOSpringValues.button)
131
- );
132
-
133
- // Interpolate animation values from `isPressed` values
134
- const pressedAnimationStyle = useAnimatedStyle(() => {
135
- // Link color states to the pressed states
136
-
137
- // Scale down button slightly when pressed
138
- const scale = interpolate(
139
- progressPressed.value,
140
- [0, 1],
141
- [1, animationScaleValue],
142
- Extrapolate.CLAMP
143
- );
144
-
145
- return {
146
- transform: [{ scale }]
147
- };
148
- });
149
-
150
- const pressedColorLabelAnimationStyle = useAnimatedStyle(() => {
151
- // Link color states to the pressed states
152
-
153
- const labelColor = interpolateColor(
154
- progressPressed.value,
121
+ const pressedColorAnimationStyle = useAnimatedStyle(() => ({
122
+ color: interpolateColor(
123
+ progress.value,
155
124
  [0, 1],
156
125
  [colorMap[color].label.default, colorMap[color].label.pressed]
157
- );
158
-
159
- return {
160
- color: labelColor
161
- };
162
- });
163
-
164
- // Animate the <Icon> color prop
165
- const pressedColorIconAnimationStyle = useAnimatedProps(() => {
166
- const iconColor = interpolateColor(
167
- progressPressed.value,
168
- [0, 1],
169
- [colorMap[color].label.default, colorMap[color].label.pressed]
170
- );
171
-
172
- return { color: iconColor };
173
- });
126
+ )
127
+ }));
174
128
 
175
129
  const AnimatedIconClassComponent =
176
130
  Animated.createAnimatedComponent(IconClassComponent);
177
131
 
178
- const onPressIn = useCallback(() => {
179
- // eslint-disable-next-line functional/immutable-data
180
- isPressed.value = 1;
181
- }, [isPressed]);
182
- const onPressOut = useCallback(() => {
183
- // eslint-disable-next-line functional/immutable-data
184
- isPressed.value = 0;
185
- }, [isPressed]);
186
-
187
132
  // Icon size
188
133
  const iconSize: IOIconSizeScale = 24;
134
+ const iconMargin: IOSpacingScale = 8;
189
135
 
190
136
  return (
191
137
  <Pressable
@@ -208,31 +154,28 @@ export const ButtonLink = React.forwardRef<View, ButtonLinkProps>(
208
154
  style={[
209
155
  IOButtonStyles.buttonLink,
210
156
  iconPosition === "end" && { flexDirection: "row-reverse" },
157
+ { columnGap: iconMargin },
211
158
  disabled ? { opacity: DISABLED_OPACITY } : {},
212
159
  /* Prevent Reanimated from overriding background colors
213
160
  if button is disabled */
214
- !disabled && pressedAnimationStyle
161
+ !disabled && !reducedMotion && scaleAnimatedStyle
215
162
  ]}
216
163
  >
217
- {icon && (
218
- <>
219
- {!disabled ? (
220
- <AnimatedIconClassComponent
221
- name={icon}
222
- animatedProps={pressedColorIconAnimationStyle}
223
- color={colorMap[color]?.label?.default}
224
- size={iconSize}
225
- />
226
- ) : (
227
- <AnimatedIcon
228
- name={icon}
229
- color={colorMap[color]?.label?.disabled}
230
- size={iconSize}
231
- />
232
- )}
233
- <HSpacer size={8} />
234
- </>
235
- )}
164
+ {icon &&
165
+ (!disabled ? (
166
+ <AnimatedIconClassComponent
167
+ name={icon}
168
+ animatedProps={pressedColorAnimationStyle}
169
+ color={colorMap[color]?.label?.default}
170
+ size={iconSize}
171
+ />
172
+ ) : (
173
+ <AnimatedIcon
174
+ name={icon}
175
+ color={colorMap[color]?.label?.disabled}
176
+ size={iconSize}
177
+ />
178
+ ))}
236
179
  <AnimatedIOText
237
180
  accessible={false}
238
181
  accessibilityElementsHidden
@@ -243,7 +186,7 @@ export const ButtonLink = React.forwardRef<View, ButtonLinkProps>(
243
186
  style={
244
187
  disabled
245
188
  ? { color: colorMap[color]?.label?.disabled }
246
- : { ...pressedColorLabelAnimationStyle }
189
+ : { ...pressedColorAnimationStyle }
247
190
  }
248
191
  numberOfLines={1}
249
192
  ellipsizeMode="tail"
@@ -1,4 +1,4 @@
1
- import React, { ComponentProps, useCallback } from "react";
1
+ import React, { ComponentProps, forwardRef } from "react";
2
2
  import {
3
3
  GestureResponderEvent,
4
4
  Pressable,
@@ -6,24 +6,19 @@ import {
6
6
  View
7
7
  } from "react-native";
8
8
  import Animated, {
9
- Extrapolate,
10
- interpolate,
11
9
  interpolateColor,
12
10
  useAnimatedProps,
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
  hexToRgba,
25
19
  useIOExperimentalDesign
26
20
  } from "../../core/";
21
+ import { useScaleAnimation } from "../../hooks";
27
22
  import { WithTestID } from "../../utils/types";
28
23
  import {
29
24
  AnimatedIcon,
@@ -190,6 +185,11 @@ const mapLegacyColorStates: Record<
190
185
  }
191
186
  };
192
187
 
188
+ // Icon size
189
+ const iconSize: IOIconSizeScale = 20;
190
+
191
+ const DISABLED_OPACITY = 0.5;
192
+
193
193
  // TODO: Remove this when legacy look is deprecated https://pagopa.atlassian.net/browse/IOPLT-153
194
194
  const IOButtonLegacyStylesLocal = StyleSheet.create({
195
195
  buttonWithBorder: {
@@ -197,18 +197,13 @@ const IOButtonLegacyStylesLocal = StyleSheet.create({
197
197
  }
198
198
  });
199
199
 
200
- // Icon size
201
- const iconSize: IOIconSizeScale = 20;
202
-
203
- const DISABLED_OPACITY = 0.5;
204
-
205
200
  const IOButtonStylesLocal = StyleSheet.create({
206
201
  buttonWithBorder: {
207
202
  borderWidth: 2
208
203
  }
209
204
  });
210
205
 
211
- export const ButtonOutline = React.forwardRef<View, ButtonOutline>(
206
+ export const ButtonOutline = forwardRef<View, ButtonOutline>(
212
207
  (
213
208
  {
214
209
  color = "primary",
@@ -225,7 +220,9 @@ export const ButtonOutline = React.forwardRef<View, ButtonOutline>(
225
220
  ref
226
221
  ) => {
227
222
  const { isExperimental } = useIOExperimentalDesign();
228
- const isPressed: Animated.SharedValue<number> = useSharedValue(0);
223
+ const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
224
+ useScaleAnimation();
225
+ const reducedMotion = useReducedMotion();
229
226
 
230
227
  const AnimatedIOText = Animated.createAnimatedComponent(IOText);
231
228
 
@@ -243,80 +240,48 @@ export const ButtonOutline = React.forwardRef<View, ButtonOutline>(
243
240
  () => (isExperimental ? IOButtonStylesLocal : IOButtonLegacyStylesLocal),
244
241
  [isExperimental]
245
242
  );
246
- // Scaling transformation applied when the button is pressed
247
- const animationScaleValue = IOScaleValues?.basicButton?.pressedState;
248
-
249
- // Using a spring-based animation for our interpolations
250
- const progressPressed = useDerivedValue(() =>
251
- withSpring(isPressed.value, IOSpringValues.button)
252
- );
253
243
 
254
244
  // Interpolate animation values from `isPressed` values
255
245
  const pressedAnimationStyle = useAnimatedStyle(() => {
256
246
  // Link color states to the pressed states
257
247
  const backgroundColor = interpolateColor(
258
- progressPressed.value,
248
+ progress.value,
259
249
  [0, 1],
260
250
  [colorMap[color].background.default, colorMap[color].background.pressed]
261
251
  );
262
252
 
263
253
  const borderColor = interpolateColor(
264
- progressPressed.value,
254
+ progress.value,
265
255
  [0, 1],
266
256
  [colorMap[color].border.default, colorMap[color].border.pressed]
267
257
  );
268
258
 
269
- // Scale down button slightly when pressed
270
- const scale = interpolate(
271
- progressPressed.value,
272
- [0, 1],
273
- [1, animationScaleValue],
274
- Extrapolate.CLAMP
275
- );
276
-
277
259
  return {
278
260
  borderColor,
279
- backgroundColor,
280
- transform: [{ scale }]
261
+ backgroundColor
281
262
  };
282
263
  });
283
264
 
284
- const pressedColorLabelAnimationStyle = useAnimatedStyle(() => {
285
- // Link color states to the pressed states
286
-
287
- const labelColor = interpolateColor(
288
- progressPressed.value,
265
+ const pressedColorLabelAnimationStyle = useAnimatedStyle(() => ({
266
+ color: interpolateColor(
267
+ progress.value,
289
268
  [0, 1],
290
269
  [colorMap[color].border.default, colorMap[color].border.pressed]
291
- );
292
-
293
- return {
294
- color: labelColor
295
- };
296
- });
270
+ )
271
+ }));
297
272
 
298
273
  // Animate the <Icon> color prop
299
- const pressedColorIconAnimationStyle = useAnimatedProps(() => {
300
- const iconColor = interpolateColor(
301
- progressPressed.value,
274
+ const pressedColorIconAnimationStyle = useAnimatedProps(() => ({
275
+ color: interpolateColor(
276
+ progress.value,
302
277
  [0, 1],
303
278
  [colorMap[color].label.default, colorMap[color].label.pressed]
304
- );
305
- return { color: iconColor };
306
- });
279
+ )
280
+ }));
307
281
 
308
282
  const AnimatedIconClassComponent =
309
283
  Animated.createAnimatedComponent(IconClassComponent);
310
284
 
311
- const onPressIn = useCallback(() => {
312
- // eslint-disable-next-line functional/immutable-data
313
- isPressed.value = 1;
314
- }, [isPressed]);
315
- const onPressOut = useCallback(() => {
316
- // eslint-disable-next-line functional/immutable-data
317
- isPressed.value = 0;
318
- }, [isPressed]);
319
-
320
285
  return (
321
286
  <Pressable
322
287
  ref={ref}
@@ -351,6 +316,7 @@ export const ButtonOutline = React.forwardRef<View, ButtonOutline>(
351
316
  },
352
317
  /* Prevent Reanimated from overriding background colors
353
318
  if button is disabled */
319
+ !reducedMotion && !disabled && scaleAnimatedStyle,
354
320
  !disabled && pressedAnimationStyle
355
321
  ]}
356
322
  >