@pagopa/io-app-design-system 6.0.4 → 6.0.6

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 (171) hide show
  1. package/lib/commonjs/components/badge/Badge.js +0 -4
  2. package/lib/commonjs/components/badge/Badge.js.map +1 -1
  3. package/lib/commonjs/components/banner/Banner.js +0 -4
  4. package/lib/commonjs/components/banner/Banner.js.map +1 -1
  5. package/lib/commonjs/components/buttons/IOButton/IOButton.js +0 -5
  6. package/lib/commonjs/components/buttons/IOButton/IOButton.js.map +1 -1
  7. package/lib/commonjs/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +7 -5
  8. package/lib/commonjs/components/headers/HeaderSecondLevel.js +0 -4
  9. package/lib/commonjs/components/headers/HeaderSecondLevel.js.map +1 -1
  10. package/lib/commonjs/components/listitems/ListItemInfo.js +86 -26
  11. package/lib/commonjs/components/listitems/ListItemInfo.js.map +1 -1
  12. package/lib/commonjs/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +6 -4
  13. package/lib/commonjs/components/loadingSpinner/LoadingSpinner.js +30 -23
  14. package/lib/commonjs/components/loadingSpinner/LoadingSpinner.js.map +1 -1
  15. package/lib/commonjs/components/modules/ModuleIDP.js +0 -4
  16. package/lib/commonjs/components/modules/ModuleIDP.js.map +1 -1
  17. package/lib/commonjs/components/numberpad/NumberButton.js +0 -4
  18. package/lib/commonjs/components/numberpad/NumberButton.js.map +1 -1
  19. package/lib/commonjs/components/searchInput/SearchInput.js +0 -1
  20. package/lib/commonjs/components/searchInput/SearchInput.js.map +1 -1
  21. package/lib/commonjs/components/tabs/TabItem.js +0 -4
  22. package/lib/commonjs/components/tabs/TabItem.js.map +1 -1
  23. package/lib/commonjs/components/tag/Tag.js +0 -4
  24. package/lib/commonjs/components/tag/Tag.js.map +1 -1
  25. package/lib/commonjs/components/typography/Body.js +1 -7
  26. package/lib/commonjs/components/typography/Body.js.map +1 -1
  27. package/lib/commonjs/components/typography/BodySmall.js +0 -7
  28. package/lib/commonjs/components/typography/BodySmall.js.map +1 -1
  29. package/lib/commonjs/components/typography/ButtonText.js +0 -7
  30. package/lib/commonjs/components/typography/ButtonText.js.map +1 -1
  31. package/lib/commonjs/components/typography/Caption.js +0 -4
  32. package/lib/commonjs/components/typography/Caption.js.map +1 -1
  33. package/lib/commonjs/components/typography/H1.js +0 -4
  34. package/lib/commonjs/components/typography/H1.js.map +1 -1
  35. package/lib/commonjs/components/typography/H2.js +0 -4
  36. package/lib/commonjs/components/typography/H2.js.map +1 -1
  37. package/lib/commonjs/components/typography/H3.js +0 -4
  38. package/lib/commonjs/components/typography/H3.js.map +1 -1
  39. package/lib/commonjs/components/typography/H4.js +0 -4
  40. package/lib/commonjs/components/typography/H4.js.map +1 -1
  41. package/lib/commonjs/components/typography/H5.js +0 -4
  42. package/lib/commonjs/components/typography/H5.js.map +1 -1
  43. package/lib/commonjs/components/typography/H6.js +0 -1
  44. package/lib/commonjs/components/typography/H6.js.map +1 -1
  45. package/lib/commonjs/components/typography/Hero.js +0 -4
  46. package/lib/commonjs/components/typography/Hero.js.map +1 -1
  47. package/lib/commonjs/components/typography/IOText.js +5 -1
  48. package/lib/commonjs/components/typography/IOText.js.map +1 -1
  49. package/lib/commonjs/components/typography/LabelMini.js +1 -8
  50. package/lib/commonjs/components/typography/LabelMini.js.map +1 -1
  51. package/lib/commonjs/components/typography/markdown/MdH1.js +0 -4
  52. package/lib/commonjs/components/typography/markdown/MdH1.js.map +1 -1
  53. package/lib/commonjs/components/typography/markdown/MdH2.js +0 -4
  54. package/lib/commonjs/components/typography/markdown/MdH2.js.map +1 -1
  55. package/lib/commonjs/components/typography/markdown/MdH3.js +0 -4
  56. package/lib/commonjs/components/typography/markdown/MdH3.js.map +1 -1
  57. package/lib/module/components/badge/Badge.js +1 -5
  58. package/lib/module/components/badge/Badge.js.map +1 -1
  59. package/lib/module/components/banner/Banner.js +1 -5
  60. package/lib/module/components/banner/Banner.js.map +1 -1
  61. package/lib/module/components/buttons/IOButton/IOButton.js +0 -5
  62. package/lib/module/components/buttons/IOButton/IOButton.js.map +1 -1
  63. package/lib/module/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +7 -5
  64. package/lib/module/components/headers/HeaderSecondLevel.js +1 -5
  65. package/lib/module/components/headers/HeaderSecondLevel.js.map +1 -1
  66. package/lib/module/components/listitems/ListItemInfo.js +87 -27
  67. package/lib/module/components/listitems/ListItemInfo.js.map +1 -1
  68. package/lib/module/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +6 -4
  69. package/lib/module/components/loadingSpinner/LoadingSpinner.js +30 -24
  70. package/lib/module/components/loadingSpinner/LoadingSpinner.js.map +1 -1
  71. package/lib/module/components/modules/ModuleIDP.js +1 -5
  72. package/lib/module/components/modules/ModuleIDP.js.map +1 -1
  73. package/lib/module/components/numberpad/NumberButton.js +1 -5
  74. package/lib/module/components/numberpad/NumberButton.js.map +1 -1
  75. package/lib/module/components/searchInput/SearchInput.js +0 -1
  76. package/lib/module/components/searchInput/SearchInput.js.map +1 -1
  77. package/lib/module/components/tabs/TabItem.js +1 -5
  78. package/lib/module/components/tabs/TabItem.js.map +1 -1
  79. package/lib/module/components/tag/Tag.js +1 -5
  80. package/lib/module/components/tag/Tag.js.map +1 -1
  81. package/lib/module/components/typography/Body.js +2 -8
  82. package/lib/module/components/typography/Body.js.map +1 -1
  83. package/lib/module/components/typography/BodySmall.js +1 -8
  84. package/lib/module/components/typography/BodySmall.js.map +1 -1
  85. package/lib/module/components/typography/ButtonText.js +0 -7
  86. package/lib/module/components/typography/ButtonText.js.map +1 -1
  87. package/lib/module/components/typography/Caption.js +1 -5
  88. package/lib/module/components/typography/Caption.js.map +1 -1
  89. package/lib/module/components/typography/H1.js +1 -5
  90. package/lib/module/components/typography/H1.js.map +1 -1
  91. package/lib/module/components/typography/H2.js +1 -5
  92. package/lib/module/components/typography/H2.js.map +1 -1
  93. package/lib/module/components/typography/H3.js +1 -5
  94. package/lib/module/components/typography/H3.js.map +1 -1
  95. package/lib/module/components/typography/H4.js +1 -5
  96. package/lib/module/components/typography/H4.js.map +1 -1
  97. package/lib/module/components/typography/H5.js +1 -5
  98. package/lib/module/components/typography/H5.js.map +1 -1
  99. package/lib/module/components/typography/H6.js +0 -1
  100. package/lib/module/components/typography/H6.js.map +1 -1
  101. package/lib/module/components/typography/Hero.js +1 -5
  102. package/lib/module/components/typography/Hero.js.map +1 -1
  103. package/lib/module/components/typography/IOText.js +6 -2
  104. package/lib/module/components/typography/IOText.js.map +1 -1
  105. package/lib/module/components/typography/LabelMini.js +2 -9
  106. package/lib/module/components/typography/LabelMini.js.map +1 -1
  107. package/lib/module/components/typography/markdown/MdH1.js +1 -5
  108. package/lib/module/components/typography/markdown/MdH1.js.map +1 -1
  109. package/lib/module/components/typography/markdown/MdH2.js +1 -5
  110. package/lib/module/components/typography/markdown/MdH2.js.map +1 -1
  111. package/lib/module/components/typography/markdown/MdH3.js +1 -5
  112. package/lib/module/components/typography/markdown/MdH3.js.map +1 -1
  113. package/lib/typescript/components/badge/Badge.d.ts.map +1 -1
  114. package/lib/typescript/components/banner/Banner.d.ts.map +1 -1
  115. package/lib/typescript/components/buttons/IOButton/IOButton.d.ts.map +1 -1
  116. package/lib/typescript/components/headers/HeaderSecondLevel.d.ts.map +1 -1
  117. package/lib/typescript/components/listitems/ListItemInfo.d.ts +29 -0
  118. package/lib/typescript/components/listitems/ListItemInfo.d.ts.map +1 -1
  119. package/lib/typescript/components/loadingSpinner/LoadingSpinner.d.ts +2 -3
  120. package/lib/typescript/components/loadingSpinner/LoadingSpinner.d.ts.map +1 -1
  121. package/lib/typescript/components/modules/ModuleIDP.d.ts.map +1 -1
  122. package/lib/typescript/components/numberpad/NumberButton.d.ts.map +1 -1
  123. package/lib/typescript/components/searchInput/SearchInput.d.ts.map +1 -1
  124. package/lib/typescript/components/tabs/TabItem.d.ts.map +1 -1
  125. package/lib/typescript/components/tag/Tag.d.ts.map +1 -1
  126. package/lib/typescript/components/typography/Body.d.ts.map +1 -1
  127. package/lib/typescript/components/typography/BodySmall.d.ts.map +1 -1
  128. package/lib/typescript/components/typography/ButtonText.d.ts.map +1 -1
  129. package/lib/typescript/components/typography/Caption.d.ts.map +1 -1
  130. package/lib/typescript/components/typography/H1.d.ts.map +1 -1
  131. package/lib/typescript/components/typography/H2.d.ts.map +1 -1
  132. package/lib/typescript/components/typography/H3.d.ts.map +1 -1
  133. package/lib/typescript/components/typography/H4.d.ts.map +1 -1
  134. package/lib/typescript/components/typography/H5.d.ts.map +1 -1
  135. package/lib/typescript/components/typography/H6.d.ts.map +1 -1
  136. package/lib/typescript/components/typography/Hero.d.ts.map +1 -1
  137. package/lib/typescript/components/typography/IOText.d.ts.map +1 -1
  138. package/lib/typescript/components/typography/LabelMini.d.ts.map +1 -1
  139. package/lib/typescript/components/typography/markdown/MdH1.d.ts.map +1 -1
  140. package/lib/typescript/components/typography/markdown/MdH2.d.ts.map +1 -1
  141. package/lib/typescript/components/typography/markdown/MdH3.d.ts.map +1 -1
  142. package/package.json +1 -1
  143. package/src/components/badge/Badge.tsx +1 -3
  144. package/src/components/banner/Banner.tsx +1 -3
  145. package/src/components/buttons/IOButton/IOButton.tsx +0 -3
  146. package/src/components/claimsSelector/__test__/__snapshots__/ClaimsSelector.test.tsx.snap +7 -5
  147. package/src/components/headers/HeaderSecondLevel.tsx +1 -4
  148. package/src/components/listitems/ListItemInfo.tsx +124 -49
  149. package/src/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +6 -4
  150. package/src/components/loadingSpinner/LoadingSpinner.tsx +26 -33
  151. package/src/components/modules/ModuleIDP.tsx +1 -3
  152. package/src/components/numberpad/NumberButton.tsx +1 -3
  153. package/src/components/searchInput/SearchInput.tsx +0 -1
  154. package/src/components/tabs/TabItem.tsx +2 -8
  155. package/src/components/tag/Tag.tsx +1 -3
  156. package/src/components/typography/Body.tsx +3 -8
  157. package/src/components/typography/BodySmall.tsx +2 -7
  158. package/src/components/typography/ButtonText.tsx +2 -7
  159. package/src/components/typography/Caption.tsx +1 -3
  160. package/src/components/typography/H1.tsx +1 -3
  161. package/src/components/typography/H2.tsx +1 -3
  162. package/src/components/typography/H3.tsx +1 -3
  163. package/src/components/typography/H4.tsx +1 -3
  164. package/src/components/typography/H5.tsx +1 -3
  165. package/src/components/typography/H6.tsx +0 -1
  166. package/src/components/typography/Hero.tsx +1 -3
  167. package/src/components/typography/IOText.tsx +16 -3
  168. package/src/components/typography/LabelMini.tsx +3 -8
  169. package/src/components/typography/markdown/MdH1.tsx +1 -3
  170. package/src/components/typography/markdown/MdH2.tsx +1 -3
  171. package/src/components/typography/markdown/MdH3.tsx +1 -3
@@ -1,5 +1,5 @@
1
1
  import { ComponentProps, ReactNode } from "react";
2
- import { AccessibilityRole, Platform, Pressable, View } from "react-native";
2
+ import { AccessibilityRole, Pressable, View } from "react-native";
3
3
  import Animated from "react-native-reanimated";
4
4
  import { useIOTheme } from "../../context";
5
5
  import { IOListItemStyles, IOListItemVisualParams } from "../../core";
@@ -35,14 +35,8 @@ type EndElementProps =
35
35
  | BadgeProps;
36
36
 
37
37
  type GraphicProps =
38
- | {
39
- paymentLogoIcon?: IOLogoPaymentType;
40
- icon?: never;
41
- }
42
- | {
43
- paymentLogoIcon?: never;
44
- icon?: IOIcons;
45
- };
38
+ | { paymentLogoIcon?: IOLogoPaymentType; icon?: never }
39
+ | { paymentLogoIcon?: never; icon?: IOIcons };
46
40
 
47
41
  type InteractiveProps = Pick<
48
42
  ComponentProps<typeof Pressable>,
@@ -55,7 +49,6 @@ export type ListItemInfo = WithTestID<{
55
49
  numberOfLines?: number;
56
50
  endElement?: EndElementProps;
57
51
  topElement?: BadgeProps;
58
- // Accessibility
59
52
  accessibilityLabel?: string;
60
53
  accessibilityRole?: AccessibilityRole;
61
54
  reversed?: boolean;
@@ -72,16 +65,16 @@ const EndElementComponent = ({ type, componentProps }: EndElementProps) => {
72
65
  <IOButton
73
66
  variant="link"
74
67
  {...componentProps}
75
- accessibilityLabel={`${
68
+ accessibilityLabel={
76
69
  componentProps.accessibilityLabel ?? componentProps.label
77
- }`}
70
+ }
78
71
  />
79
72
  );
80
73
  case "iconButton":
81
74
  return (
82
75
  <IconButton
83
76
  {...componentProps}
84
- accessibilityLabel={`${componentProps.accessibilityLabel}`}
77
+ accessibilityLabel={componentProps.accessibilityLabel}
85
78
  />
86
79
  );
87
80
  case "badge":
@@ -99,7 +92,9 @@ const ListItemInfoContent = ({
99
92
  numberOfLines,
100
93
  reversed,
101
94
  topElement,
102
- endElement
95
+ endElement,
96
+ hasInteractiveElements,
97
+ listItemAccessibilityLabel
103
98
  }: Pick<
104
99
  ListItemInfo,
105
100
  | "icon"
@@ -110,7 +105,10 @@ const ListItemInfoContent = ({
110
105
  | "reversed"
111
106
  | "topElement"
112
107
  | "endElement"
113
- >) => {
108
+ > & {
109
+ hasInteractiveElements: boolean;
110
+ listItemAccessibilityLabel?: string;
111
+ }) => {
114
112
  const theme = useIOTheme();
115
113
  const { hugeFontEnabled } = useIOFontDynamicScale();
116
114
 
@@ -124,15 +122,23 @@ const ListItemInfoContent = ({
124
122
  size={IOListItemVisualParams.iconSize}
125
123
  />
126
124
  )}
125
+
127
126
  {paymentLogoIcon && (
128
127
  <LogoPaymentWithFallback
129
128
  brand={paymentLogoIcon}
130
129
  size={PAYMENT_LOGO_SIZE}
131
130
  />
132
131
  )}
132
+
133
133
  <View style={{ flex: 1 }}>
134
134
  <View
135
- accessible={Platform.OS === "ios"}
135
+ accessible={hasInteractiveElements}
136
+ accessibilityLabel={
137
+ hasInteractiveElements ? listItemAccessibilityLabel : undefined
138
+ }
139
+ importantForAccessibility={
140
+ hasInteractiveElements ? "yes" : "no-hide-descendants"
141
+ }
136
142
  style={{ flexDirection: reversed ? "column-reverse" : "column" }}
137
143
  >
138
144
  {topElement?.type === "badge" && (
@@ -141,11 +147,13 @@ const ListItemInfoContent = ({
141
147
  <VSpacer size={4} />
142
148
  </View>
143
149
  )}
150
+
144
151
  {label && (
145
152
  <BodySmall weight="Regular" color={theme["textBody-tertiary"]}>
146
153
  {label}
147
154
  </BodySmall>
148
155
  )}
156
+
149
157
  {typeof value === "string" ? (
150
158
  <H6 color={theme["textBody-default"]} numberOfLines={numberOfLines}>
151
159
  {value}
@@ -155,8 +163,14 @@ const ListItemInfoContent = ({
155
163
  )}
156
164
  </View>
157
165
  </View>
166
+
158
167
  {endElement && (
159
- <View>
168
+ <View
169
+ accessible={false}
170
+ importantForAccessibility={
171
+ hasInteractiveElements ? "auto" : "no-hide-descendants"
172
+ }
173
+ >
160
174
  <EndElementComponent {...endElement} />
161
175
  </View>
162
176
  )}
@@ -164,6 +178,35 @@ const ListItemInfoContent = ({
164
178
  );
165
179
  };
166
180
 
181
+ /**
182
+ * ListItemInfo component displays information in a list item format with optional icons,
183
+ * labels, values, and end elements (buttons, badges).
184
+ *
185
+ * @remarks
186
+ * **Accessibility for Interactive Elements:**
187
+ * When using interactive end elements (`buttonLink` or `iconButton`), you must provide
188
+ * an appropriate `accessibilityLabel` directly to the interactive component props.
189
+ * This ensures that screen reader users can understand the relationship between the
190
+ * list item content and the action that the interactive element triggers.
191
+ *
192
+ * Example:
193
+ * ```tsx
194
+ * <ListItemInfo
195
+ * label="Email"
196
+ * value="user@example.com"
197
+ * endElement={{
198
+ * type: "buttonLink",
199
+ * componentProps: {
200
+ * label: "Edit",
201
+ * accessibilityLabel: "Edit email address"
202
+ * }
203
+ * }}
204
+ * />
205
+ * ```
206
+ *
207
+ * The design system cannot enforce this pattern automatically, so it's the responsibility
208
+ * of the implementing software engineer to ensure proper accessibility labels are set.
209
+ */
167
210
  export const ListItemInfo = ({
168
211
  value,
169
212
  label,
@@ -185,13 +228,41 @@ export const ListItemInfo = ({
185
228
  const { onPressIn, onPressOut, scaleAnimatedStyle, backgroundAnimatedStyle } =
186
229
  useListItemAnimation();
187
230
 
231
+ /**
232
+ * A11Y Support: Two different combinations based on interactive elements
233
+ *
234
+ * 1. NO interactive elements (or just badge):
235
+ * - The outer container is accessible and receives the complete accessibility label
236
+ * - This allows the entire list item to be treated as a single accessibility element
237
+ *
238
+ * 2. WITH interactive elements (buttonLink or iconButton):
239
+ * - The outer container is NOT accessible
240
+ * - The inner content becomes accessible with its label
241
+ * - The interactive element is separately accessible with its own label
242
+ * - This allows screen readers to navigate between the content and the action separately
243
+ */
244
+ const hasInteractiveElements =
245
+ endElement?.type === "buttonLink" || endElement?.type === "iconButton";
246
+
188
247
  const componentValueToAccessibility = typeof value === "string" ? value : "";
189
248
 
249
+ const topBadgeText =
250
+ topElement?.type === "badge" ? topElement.componentProps.text ?? "" : "";
251
+
252
+ const endBadgeText =
253
+ endElement?.type === "badge" ? endElement.componentProps.text ?? "" : "";
254
+
255
+ /**
256
+ * Build text in VISUAL ORDER
257
+ */
258
+ const mainTextParts = reversed
259
+ ? [componentValueToAccessibility, label]
260
+ : [label, componentValueToAccessibility];
261
+
262
+ const textParts = [topBadgeText, ...mainTextParts, endBadgeText];
263
+
190
264
  const listItemAccessibilityLabel =
191
- accessibilityLabel ??
192
- (label
193
- ? `${label}; ${componentValueToAccessibility}`
194
- : componentValueToAccessibility);
265
+ accessibilityLabel ?? textParts.filter(Boolean).join("; ");
195
266
 
196
267
  const contentProps = {
197
268
  icon,
@@ -201,7 +272,9 @@ export const ListItemInfo = ({
201
272
  numberOfLines,
202
273
  reversed,
203
274
  topElement,
204
- endElement
275
+ endElement,
276
+ hasInteractiveElements,
277
+ listItemAccessibilityLabel
205
278
  } as const;
206
279
 
207
280
  if (onLongPress) {
@@ -209,14 +282,14 @@ export const ListItemInfo = ({
209
282
  <Pressable
210
283
  onLongPress={onLongPress}
211
284
  testID={testID}
212
- accessible={!endElement}
213
- onPressIn={onPressIn}
214
- onPressOut={onPressOut}
215
- onTouchEnd={onPressOut}
216
- accessibilityRole={"button"}
285
+ accessible
286
+ accessibilityRole="button"
217
287
  accessibilityLabel={listItemAccessibilityLabel}
218
288
  accessibilityActions={accessibilityActions}
219
289
  onAccessibilityAction={onAccessibilityAction}
290
+ onPressIn={onPressIn}
291
+ onPressOut={onPressOut}
292
+ onTouchEnd={onPressOut}
220
293
  >
221
294
  <Animated.View
222
295
  style={[IOListItemStyles.listItem, backgroundAnimatedStyle]}
@@ -238,29 +311,31 @@ export const ListItemInfo = ({
238
311
  </Animated.View>
239
312
  </Pressable>
240
313
  );
241
- } else {
242
- return (
314
+ }
315
+
316
+ return (
317
+ <View
318
+ style={IOListItemStyles.listItem}
319
+ testID={testID}
320
+ accessible={!hasInteractiveElements}
321
+ accessibilityLabel={
322
+ hasInteractiveElements ? undefined : listItemAccessibilityLabel
323
+ }
324
+ accessibilityRole={hasInteractiveElements ? undefined : accessibilityRole}
325
+ >
243
326
  <View
244
- style={IOListItemStyles.listItem}
245
- testID={testID}
246
- accessible={!endElement}
247
- accessibilityLabel={listItemAccessibilityLabel}
248
- accessibilityRole={accessibilityRole}
327
+ style={[
328
+ IOListItemStyles.listItemInner,
329
+ {
330
+ columnGap:
331
+ IOListItemVisualParams.iconMargin *
332
+ dynamicFontScale *
333
+ spacingScaleMultiplier
334
+ }
335
+ ]}
249
336
  >
250
- <View
251
- style={[
252
- IOListItemStyles.listItemInner,
253
- {
254
- columnGap:
255
- IOListItemVisualParams.iconMargin *
256
- dynamicFontScale *
257
- spacingScaleMultiplier
258
- }
259
- ]}
260
- >
261
- <ListItemInfoContent {...contentProps} />
262
- </View>
337
+ <ListItemInfoContent {...contentProps} />
263
338
  </View>
264
- );
265
- }
339
+ </View>
340
+ );
266
341
  };
@@ -190,7 +190,8 @@ exports[`Test List Item Components - Experimental Enabled ListItemInfo Snapshot
190
190
  }
191
191
  >
192
192
  <View
193
- accessible={true}
193
+ accessible={false}
194
+ importantForAccessibility="no-hide-descendants"
194
195
  style={
195
196
  {
196
197
  "flexDirection": "column",
@@ -1379,7 +1380,7 @@ exports[`Test List Item Components - Experimental Enabled ListItemRadioWithAmou
1379
1380
  <RNSVGPath
1380
1381
  d="m7 12 4 4 7-7"
1381
1382
  fill={null}
1382
- onLayout={[Function]}
1383
+ onSvgLayout={[Function]}
1383
1384
  propList={
1384
1385
  [
1385
1386
  "fill",
@@ -2308,7 +2309,8 @@ exports[`Test List Item Components ListItemInfo Snapshot 1`] = `
2308
2309
  }
2309
2310
  >
2310
2311
  <View
2311
- accessible={true}
2312
+ accessible={false}
2313
+ importantForAccessibility="no-hide-descendants"
2312
2314
  style={
2313
2315
  {
2314
2316
  "flexDirection": "column",
@@ -3497,7 +3499,7 @@ exports[`Test List Item Components ListItemRadioWithAmount Snapshot 1`] = `
3497
3499
  <RNSVGPath
3498
3500
  d="m7 12 4 4 7-7"
3499
3501
  fill={null}
3500
- onLayout={[Function]}
3502
+ onSvgLayout={[Function]}
3501
3503
  propList={
3502
3504
  [
3503
3505
  "fill",
@@ -1,12 +1,6 @@
1
- import { ReactElement, useEffect } from "react";
1
+ import { ReactElement, useId } from "react";
2
2
  import { ColorValue, View } from "react-native";
3
- import Animated, {
4
- Easing,
5
- useAnimatedStyle,
6
- useSharedValue,
7
- withRepeat,
8
- withTiming
9
- } from "react-native-reanimated";
3
+ import Animated from "react-native-reanimated";
10
4
  import Svg, { Defs, G, LinearGradient, Path, Stop } from "react-native-svg";
11
5
  import { useIOTheme } from "../../context";
12
6
  import { IOColors } from "../../core/IOColors";
@@ -21,15 +15,18 @@ export type LoadingSpinner = WithTestID<{
21
15
  }>;
22
16
 
23
17
  /**
24
- * Size scale, 76 is kept for backward compatibility with the old design system but 48 is enough for the new one.
25
- * It will be removed in the future.
18
+ * Size scale
26
19
  */
27
- export type IOLoadingSpinnerSizeScale = 24 | 48 | 76;
20
+ export type IOLoadingSpinnerSizeScale = 24 | 48;
28
21
 
29
- const strokeMap: Record<NonNullable<LoadingSpinner["size"]>, number> = {
22
+ const spinKeyframes = {
23
+ from: { transform: [{ rotateZ: "0deg" }] },
24
+ to: { transform: [{ rotateZ: "360deg" }] }
25
+ };
26
+
27
+ const strokeMap: Record<IOLoadingSpinnerSizeScale, number> = {
30
28
  24: 3,
31
- 48: 5,
32
- 76: 7
29
+ 48: 5
33
30
  };
34
31
 
35
32
  export const LoadingSpinner = ({
@@ -41,23 +38,13 @@ export const LoadingSpinner = ({
41
38
  testID = "LoadingSpinnerTestID"
42
39
  }: LoadingSpinner): ReactElement => {
43
40
  const theme = useIOTheme();
44
- const rotation = useSharedValue(0);
45
- const stroke: number = strokeMap[size];
41
+ const id = useId();
42
+ const stroke = strokeMap[size];
46
43
 
47
44
  const color = customColor ?? IOColors[theme["interactiveElem-default"]];
48
45
 
49
- useEffect(() => {
50
- // eslint-disable-next-line functional/immutable-data
51
- rotation.value = withRepeat(
52
- withTiming(360, { duration: durationMs, easing: Easing.linear }),
53
- -1,
54
- false
55
- );
56
- }, [durationMs, rotation]);
57
-
58
- const animatedStyle = useAnimatedStyle(() => ({
59
- transform: [{ rotateZ: `${rotation.value}deg` }]
60
- }));
46
+ const secondHalfId = `${id}-secondHalf`;
47
+ const firstHalfId = `${id}-firstHalf`;
61
48
 
62
49
  return (
63
50
  <View
@@ -70,7 +57,13 @@ export const LoadingSpinner = ({
70
57
  >
71
58
  <Animated.View
72
59
  testID={"LoadingSpinnerAnimatedTestID"}
73
- style={animatedStyle}
60
+ style={{
61
+ animationName: spinKeyframes,
62
+ animationDuration: durationMs,
63
+ animationIterationCount: "infinite",
64
+ animationTimingFunction: "linear",
65
+ transformOrigin: "center"
66
+ }}
74
67
  >
75
68
  {/* Thanks to Ben Ilegbodu for the article on how to
76
69
  create a a SVG gradient loading spinner. Below is
@@ -83,11 +76,11 @@ export const LoadingSpinner = ({
83
76
  fill="none"
84
77
  >
85
78
  <Defs>
86
- <LinearGradient id="spinner-secondHalf">
79
+ <LinearGradient id={secondHalfId}>
87
80
  <Stop offset="0%" stopOpacity="0" stopColor={color} />
88
81
  <Stop offset="100%" stopOpacity="1" stopColor={color} />
89
82
  </LinearGradient>
90
- <LinearGradient id="spinner-firstHalf">
83
+ <LinearGradient id={firstHalfId}>
91
84
  <Stop offset="0%" stopOpacity="1" stopColor={color} />
92
85
  <Stop offset="100%" stopOpacity="1" stopColor={color} />
93
86
  </LinearGradient>
@@ -95,13 +88,13 @@ export const LoadingSpinner = ({
95
88
 
96
89
  <G strokeWidth={stroke}>
97
90
  <Path
98
- stroke="url(#spinner-secondHalf)"
91
+ stroke={`url(#${secondHalfId})`}
99
92
  d={`M ${stroke / 2} ${size / 2} A ${size / 2 - stroke / 2} ${
100
93
  size / 2 - stroke / 2
101
94
  } 0 0 1 ${size - stroke / 2} ${size / 2}`}
102
95
  />
103
96
  <Path
104
- stroke="url(#spinner-firstHalf)"
97
+ stroke={`url(#${firstHalfId})`}
105
98
  d={`M ${size - stroke / 2} ${size / 2} A ${
106
99
  size / 2 - stroke / 2
107
100
  } ${size / 2 - stroke / 2} 0 0 1 ${stroke / 2} ${size / 2}`}
@@ -1,5 +1,5 @@
1
1
  import { Image, ImageSourcePropType, StyleSheet } from "react-native";
2
- import { useIONewTypeface, useIOThemeContext, useIOTheme } from "../../context";
2
+ import { useIOThemeContext, useIOTheme } from "../../context";
3
3
  import { IOListItemLogoMargin } from "../../core";
4
4
  import { addCacheTimestampToUri } from "../../utils/image";
5
5
  import { IOText } from "../typography";
@@ -49,7 +49,6 @@ export const ModuleIDP = ({
49
49
  testID,
50
50
  accessibilityLabel
51
51
  }: ModuleIDP) => {
52
- const { newTypefaceEnabled } = useIONewTypeface();
53
52
  const theme = useIOTheme();
54
53
  const IDPLogoSource = useIDPLogo(logo);
55
54
 
@@ -60,7 +59,6 @@ export const ModuleIDP = ({
60
59
  withLooseSpacing={withLooseSpacing}
61
60
  >
62
61
  <IOText
63
- font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
64
62
  weight={"Semibold"}
65
63
  size={12}
66
64
  lineHeight={16}
@@ -6,7 +6,7 @@ import Animated, {
6
6
  useAnimatedStyle,
7
7
  useReducedMotion
8
8
  } from "react-native-reanimated";
9
- import { useIONewTypeface, useIOTheme } from "../../context";
9
+ import { useIOTheme } from "../../context";
10
10
  import { hexToRgba, IOColors } from "../../core";
11
11
  import { useScaleAnimation } from "../../hooks";
12
12
  import { IOText } from "../typography";
@@ -50,7 +50,6 @@ export const NumberButton = memo(
50
50
  const { progress, onPressIn, onPressOut, scaleAnimatedStyle } =
51
51
  useScaleAnimation("medium");
52
52
  const reducedMotion = useReducedMotion();
53
- const { newTypefaceEnabled } = useIONewTypeface();
54
53
 
55
54
  const colorMap: Record<NumberButtonVariantType, ColorMapVariant> = useMemo(
56
55
  () => ({
@@ -103,7 +102,6 @@ export const NumberButton = memo(
103
102
  >
104
103
  <IOText
105
104
  size={22}
106
- font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
107
105
  weight="Semibold"
108
106
  color={colorMap[variant].foreground}
109
107
  style={{
@@ -307,7 +307,6 @@ export const SearchInput = forwardRef<SearchInputRef, SearchInputProps>(
307
307
  >
308
308
  <IOText
309
309
  color={theme["interactiveElem-default"]}
310
- font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
311
310
  weight={"Semibold"}
312
311
  size={buttonTextFontSize}
313
312
  lineHeight={buttonTextLineHeight}
@@ -13,7 +13,7 @@ import Animated, {
13
13
  useReducedMotion,
14
14
  withSpring
15
15
  } from "react-native-reanimated";
16
- import { useIONewTypeface, useIOTheme } from "../../context";
16
+ import { useIOTheme } from "../../context";
17
17
  import { IOColors, IOSpringValues, hexToRgba } from "../../core";
18
18
  import { useScaleAnimation } from "../../hooks";
19
19
  import { WithTestID } from "../../utils/types";
@@ -77,7 +77,6 @@ const TabItem = forwardRef(
77
77
  useScaleAnimation("medium");
78
78
  const theme = useIOTheme();
79
79
  const reducedMotion = useReducedMotion();
80
- const { newTypefaceEnabled } = useIONewTypeface();
81
80
 
82
81
  const mapColorStates: Record<
83
82
  NonNullable<TabItem["color"]>,
@@ -199,12 +198,7 @@ const TabItem = forwardRef(
199
198
  {activeIcon && (
200
199
  <Icon name={activeIcon} color={foregroundColor} size={16} />
201
200
  )}
202
- <IOText
203
- size={14}
204
- font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
205
- weight="Semibold"
206
- color={foregroundColor}
207
- >
201
+ <IOText size={14} weight="Semibold" color={foregroundColor}>
208
202
  {label}
209
203
  </IOText>
210
204
  </Animated.View>
@@ -1,5 +1,5 @@
1
1
  import { Platform, StyleSheet, View, ViewStyle } from "react-native";
2
- import { useIONewTypeface, useIOTheme } from "../../context";
2
+ import { useIOTheme } from "../../context";
3
3
  import {
4
4
  IOColors,
5
5
  IOSpacingScale,
@@ -155,7 +155,6 @@ export const Tag = ({
155
155
  forceLightMode = false
156
156
  }: Tag) => {
157
157
  const theme = useIOTheme();
158
- const { newTypefaceEnabled } = useIONewTypeface();
159
158
  const { dynamicFontScale, spacingScaleMultiplier } = useIOFontDynamicScale();
160
159
 
161
160
  const variantProps = getVariantProps(variant, icon);
@@ -203,7 +202,6 @@ export const Tag = ({
203
202
  {text && (
204
203
  <IOText
205
204
  allowFontScaling={allowFontScaling}
206
- font={newTypefaceEnabled ? "Titillio" : "TitilliumSansPro"}
207
205
  weight={"Semibold"}
208
206
  size={12}
209
207
  lineHeight={16}
@@ -1,7 +1,7 @@
1
1
  import { ForwardedRef, forwardRef } from "react";
2
2
  import { Pressable, View } from "react-native";
3
- import { useIONewTypeface, useIOTheme } from "../../context";
4
- import { IOFontFamily, IOFontWeight } from "../../utils/fonts";
3
+ import { useIOTheme } from "../../context";
4
+ import { IOFontWeight } from "../../utils/fonts";
5
5
  import {
6
6
  IOText,
7
7
  IOTextProps,
@@ -16,9 +16,6 @@ type BodyStyleProps = TypographicStyleProps & {
16
16
  export const bodyFontSize = 16;
17
17
  export const bodyLineHeight = 24;
18
18
 
19
- const fontName: IOFontFamily = "Titillio";
20
- const legacyFontName: IOFontFamily = "TitilliumSansPro";
21
-
22
19
  /**
23
20
  * `Body` typographic style
24
21
  */
@@ -37,7 +34,6 @@ export const Body = forwardRef<View, BodyStyleProps>(
37
34
  ref?: ForwardedRef<View>
38
35
  ) => {
39
36
  const theme = useIOTheme();
40
- const { newTypefaceEnabled } = useIONewTypeface();
41
37
 
42
38
  const defaultColor = asLink
43
39
  ? theme["interactiveElem-default"]
@@ -46,8 +42,7 @@ export const Body = forwardRef<View, BodyStyleProps>(
46
42
  const BodyProps: IOTextProps = {
47
43
  ...props,
48
44
  dynamicTypeRamp: "body", // iOS only
49
- font: newTypefaceEnabled ? fontName : legacyFontName,
50
- weight: customWeight ? customWeight : "Regular",
45
+ weight: customWeight || "Regular",
51
46
  size: bodyFontSize,
52
47
  lineHeight: bodyLineHeight,
53
48
  color: customColor ?? defaultColor,
@@ -1,7 +1,7 @@
1
1
  import { ForwardedRef, forwardRef } from "react";
2
2
  import { Pressable, View } from "react-native";
3
- import { useIONewTypeface, useIOTheme } from "../../context";
4
- import { IOFontFamily, IOFontWeight } from "../../utils/fonts";
3
+ import { useIOTheme } from "../../context";
4
+ import { IOFontWeight } from "../../utils/fonts";
5
5
  import {
6
6
  IOText,
7
7
  IOTextProps,
@@ -13,9 +13,6 @@ type BodySmallProps = TypographicStyleProps & {
13
13
  weight?: Extract<IOFontWeight, "Regular" | "Semibold">;
14
14
  } & TypographicStyleAsLinkProps;
15
15
 
16
- const fontName: IOFontFamily = "Titillio";
17
- const legacyFontName: IOFontFamily = "TitilliumSansPro";
18
-
19
16
  /**
20
17
  * `BodySmall` typographic style
21
18
  */
@@ -34,7 +31,6 @@ export const BodySmall = forwardRef<View, BodySmallProps>(
34
31
  ref?: ForwardedRef<View>
35
32
  ) => {
36
33
  const theme = useIOTheme();
37
- const { newTypefaceEnabled } = useIONewTypeface();
38
34
 
39
35
  const defaultColor = asLink
40
36
  ? theme["interactiveElem-default"]
@@ -43,7 +39,6 @@ export const BodySmall = forwardRef<View, BodySmallProps>(
43
39
  const BodySmallProps: IOTextProps = {
44
40
  ...props,
45
41
  dynamicTypeRamp: "footnote" /* iOS only */,
46
- font: newTypefaceEnabled ? fontName : legacyFontName,
47
42
  weight: customWeight ?? "Regular",
48
43
  size: 14,
49
44
  lineHeight: 21,
@@ -1,8 +1,8 @@
1
1
  import { ForwardedRef, forwardRef } from "react";
2
2
  import { View } from "react-native";
3
- import { useIONewTypeface } from "../../context";
3
+
4
4
  import { IOColors } from "../../core";
5
- import { IOFontFamily, IOFontSize } from "../../utils/fonts";
5
+ import { IOFontSize } from "../../utils/fonts";
6
6
  import { IOText, IOTextProps, TypographicStyleProps } from "./IOText";
7
7
 
8
8
  export const buttonTextFontSize: IOFontSize = 16;
@@ -11,19 +11,14 @@ export const buttonTextLineHeight = 20;
11
11
  /* Needed to render `ButtonOutline` and`ButtonLink` because they use
12
12
  `AnimatedText` for color transition through Reanimated */
13
13
  const defaultColor: IOColors = "white";
14
- const fontName: IOFontFamily = "Titillio";
15
- const legacyFontName: IOFontFamily = "TitilliumSansPro";
16
14
 
17
15
  /**
18
16
  * `ButtonText` typographic style
19
17
  */
20
18
  export const ButtonText = forwardRef<View, TypographicStyleProps>(
21
19
  ({ color: customColor, ...props }, ref?: ForwardedRef<View>) => {
22
- const { newTypefaceEnabled } = useIONewTypeface();
23
-
24
20
  const ButtonTextProps: IOTextProps = {
25
21
  ...props,
26
- font: newTypefaceEnabled ? fontName : legacyFontName,
27
22
  weight: "Semibold",
28
23
  size: buttonTextFontSize,
29
24
  lineHeight: buttonTextLineHeight,
@@ -1,6 +1,6 @@
1
1
  import { ForwardedRef, forwardRef } from "react";
2
2
  import { View } from "react-native";
3
- import { useIONewTypeface, useIOTheme } from "../../context";
3
+ import { useIOTheme } from "../../context";
4
4
  import { IOFontSize } from "../../utils/fonts";
5
5
  import { IOText, IOTextProps, TypographicStyleProps } from "./IOText";
6
6
 
@@ -12,12 +12,10 @@ export const captionFontSize: IOFontSize = 12;
12
12
  export const Caption = forwardRef<View, TypographicStyleProps>(
13
13
  ({ color: customColor, ...props }, ref?: ForwardedRef<View>) => {
14
14
  const theme = useIOTheme();
15
- const { newTypefaceEnabled } = useIONewTypeface();
16
15
 
17
16
  const CaptionProps: IOTextProps = {
18
17
  ...props,
19
18
  dynamicTypeRamp: "caption1", // iOS only
20
- font: newTypefaceEnabled ? "Titillio" : "TitilliumSansPro",
21
19
  weight: "Regular",
22
20
  size: captionFontSize,
23
21
  color: customColor ?? theme["textBody-default"],