@pagopa/io-app-design-system 3.0.1 → 4.0.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 (277) hide show
  1. package/lib/commonjs/components/alert/Alert.js +1 -2
  2. package/lib/commonjs/components/alert/Alert.js.map +1 -1
  3. package/lib/commonjs/components/alert/AlertEdgeToEdge.js +2 -2
  4. package/lib/commonjs/components/alert/AlertEdgeToEdge.js.map +1 -1
  5. package/lib/commonjs/components/banner/Banner.js +1 -1
  6. package/lib/commonjs/components/banner/Banner.js.map +1 -1
  7. package/lib/commonjs/components/banner/__test__/__snapshots__/banner.test.tsx.snap +2 -2
  8. package/lib/commonjs/components/buttons/ButtonLink.js +1 -1
  9. package/lib/commonjs/components/buttons/ButtonLink.js.map +1 -1
  10. package/lib/commonjs/components/buttons/ButtonOutline.js +1 -1
  11. package/lib/commonjs/components/buttons/ButtonOutline.js.map +1 -1
  12. package/lib/commonjs/components/buttons/__test__/__snapshots__/button.test.tsx.snap +3 -3
  13. package/lib/commonjs/components/featureInfo/FeatureInfo.js +3 -2
  14. package/lib/commonjs/components/featureInfo/FeatureInfo.js.map +1 -1
  15. package/lib/commonjs/components/index.js +11 -0
  16. package/lib/commonjs/components/index.js.map +1 -1
  17. package/lib/commonjs/components/layout/HeaderFirstLevel.js +1 -0
  18. package/lib/commonjs/components/layout/HeaderFirstLevel.js.map +1 -1
  19. package/lib/commonjs/components/listitems/ListItemCheckbox.js +1 -1
  20. package/lib/commonjs/components/listitems/ListItemCheckbox.js.map +1 -1
  21. package/lib/commonjs/components/listitems/ListItemInfo.js +1 -1
  22. package/lib/commonjs/components/listitems/ListItemInfo.js.map +1 -1
  23. package/lib/commonjs/components/listitems/ListItemInfoCopy.js +1 -1
  24. package/lib/commonjs/components/listitems/ListItemInfoCopy.js.map +1 -1
  25. package/lib/commonjs/components/listitems/ListItemNav.js +1 -1
  26. package/lib/commonjs/components/listitems/ListItemNav.js.map +1 -1
  27. package/lib/commonjs/components/listitems/ListItemNavAlert.js +1 -1
  28. package/lib/commonjs/components/listitems/ListItemNavAlert.js.map +1 -1
  29. package/lib/commonjs/components/listitems/ListItemRadio.js +1 -1
  30. package/lib/commonjs/components/listitems/ListItemRadio.js.map +1 -1
  31. package/lib/commonjs/components/listitems/ListItemRadioWithAmount.js +2 -2
  32. package/lib/commonjs/components/listitems/ListItemRadioWithAmount.js.map +1 -1
  33. package/lib/commonjs/components/listitems/ListItemSwitch.js +1 -1
  34. package/lib/commonjs/components/listitems/ListItemSwitch.js.map +1 -1
  35. package/lib/commonjs/components/listitems/ListItemTransaction.js +2 -2
  36. package/lib/commonjs/components/listitems/ListItemTransaction.js.map +1 -1
  37. package/lib/commonjs/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +7 -7
  38. package/lib/commonjs/components/modules/ModuleAttachment.js +1 -1
  39. package/lib/commonjs/components/modules/ModuleAttachment.js.map +1 -1
  40. package/lib/commonjs/components/modules/ModuleCheckout.js +1 -1
  41. package/lib/commonjs/components/modules/ModuleCheckout.js.map +1 -1
  42. package/lib/commonjs/components/modules/ModuleCredential.js +1 -1
  43. package/lib/commonjs/components/modules/ModuleCredential.js.map +1 -1
  44. package/lib/commonjs/components/modules/ModuleNavigation.js +3 -2
  45. package/lib/commonjs/components/modules/ModuleNavigation.js.map +1 -1
  46. package/lib/commonjs/components/modules/ModulePaymentNotice.js +2 -2
  47. package/lib/commonjs/components/modules/ModulePaymentNotice.js.map +1 -1
  48. package/lib/commonjs/components/modules/ModuleSummary.js +1 -1
  49. package/lib/commonjs/components/modules/ModuleSummary.js.map +1 -1
  50. package/lib/commonjs/components/otpInput/BoxedInput.js +4 -6
  51. package/lib/commonjs/components/otpInput/BoxedInput.js.map +1 -1
  52. package/lib/commonjs/components/otpInput/OTPInput.js +5 -4
  53. package/lib/commonjs/components/otpInput/OTPInput.js.map +1 -1
  54. package/lib/commonjs/components/tabs/TabItem.js +1 -1
  55. package/lib/commonjs/components/tabs/TabItem.js.map +1 -1
  56. package/lib/commonjs/components/textInput/TextInputBase.js +2 -2
  57. package/lib/commonjs/components/textInput/TextInputBase.js.map +1 -1
  58. package/lib/commonjs/components/tooltip/Arrows.js +49 -0
  59. package/lib/commonjs/components/tooltip/Arrows.js.map +1 -0
  60. package/lib/commonjs/components/tooltip/Tooltip.js +174 -0
  61. package/lib/commonjs/components/tooltip/Tooltip.js.map +1 -0
  62. package/lib/commonjs/components/tooltip/index.js +17 -0
  63. package/lib/commonjs/components/tooltip/index.js.map +1 -0
  64. package/lib/commonjs/components/tooltip/styles.js +50 -0
  65. package/lib/commonjs/components/tooltip/styles.js.map +1 -0
  66. package/lib/commonjs/components/tooltip/utils/index.js +180 -0
  67. package/lib/commonjs/components/tooltip/utils/index.js.map +1 -0
  68. package/lib/commonjs/components/tooltip/utils/types.js +2 -0
  69. package/lib/commonjs/components/tooltip/utils/types.js.map +1 -0
  70. package/lib/commonjs/components/typography/{LabelSmall.js → BodySmall.js} +8 -10
  71. package/lib/commonjs/components/typography/BodySmall.js.map +1 -0
  72. package/lib/commonjs/components/typography/ButtonText.js +1 -3
  73. package/lib/commonjs/components/typography/ButtonText.js.map +1 -1
  74. package/lib/commonjs/components/typography/H3.js +3 -6
  75. package/lib/commonjs/components/typography/H3.js.map +1 -1
  76. package/lib/commonjs/components/typography/H6.js +4 -5
  77. package/lib/commonjs/components/typography/H6.js.map +1 -1
  78. package/lib/commonjs/components/typography/__test__/__snapshots__/typography.test.tsx.snap +118 -161
  79. package/lib/commonjs/components/typography/__test__/typography.test.js +6 -18
  80. package/lib/commonjs/components/typography/__test__/typography.test.js.map +1 -1
  81. package/lib/commonjs/components/typography/index.js +28 -72
  82. package/lib/commonjs/components/typography/index.js.map +1 -1
  83. package/lib/module/components/alert/Alert.js +2 -3
  84. package/lib/module/components/alert/Alert.js.map +1 -1
  85. package/lib/module/components/alert/AlertEdgeToEdge.js +2 -2
  86. package/lib/module/components/alert/AlertEdgeToEdge.js.map +1 -1
  87. package/lib/module/components/banner/Banner.js +2 -2
  88. package/lib/module/components/banner/Banner.js.map +1 -1
  89. package/lib/module/components/banner/__test__/__snapshots__/banner.test.tsx.snap +2 -2
  90. package/lib/module/components/buttons/ButtonLink.js +1 -1
  91. package/lib/module/components/buttons/ButtonLink.js.map +1 -1
  92. package/lib/module/components/buttons/ButtonOutline.js +1 -1
  93. package/lib/module/components/buttons/ButtonOutline.js.map +1 -1
  94. package/lib/module/components/buttons/__test__/__snapshots__/button.test.tsx.snap +3 -3
  95. package/lib/module/components/featureInfo/FeatureInfo.js +4 -3
  96. package/lib/module/components/featureInfo/FeatureInfo.js.map +1 -1
  97. package/lib/module/components/index.js +1 -0
  98. package/lib/module/components/index.js.map +1 -1
  99. package/lib/module/components/layout/HeaderFirstLevel.js +1 -0
  100. package/lib/module/components/layout/HeaderFirstLevel.js.map +1 -1
  101. package/lib/module/components/listitems/ListItemCheckbox.js +2 -2
  102. package/lib/module/components/listitems/ListItemCheckbox.js.map +1 -1
  103. package/lib/module/components/listitems/ListItemInfo.js +2 -2
  104. package/lib/module/components/listitems/ListItemInfo.js.map +1 -1
  105. package/lib/module/components/listitems/ListItemInfoCopy.js +2 -2
  106. package/lib/module/components/listitems/ListItemInfoCopy.js.map +1 -1
  107. package/lib/module/components/listitems/ListItemNav.js +2 -2
  108. package/lib/module/components/listitems/ListItemNav.js.map +1 -1
  109. package/lib/module/components/listitems/ListItemNavAlert.js +2 -2
  110. package/lib/module/components/listitems/ListItemNavAlert.js.map +1 -1
  111. package/lib/module/components/listitems/ListItemRadio.js +2 -2
  112. package/lib/module/components/listitems/ListItemRadio.js.map +1 -1
  113. package/lib/module/components/listitems/ListItemRadioWithAmount.js +3 -3
  114. package/lib/module/components/listitems/ListItemRadioWithAmount.js.map +1 -1
  115. package/lib/module/components/listitems/ListItemSwitch.js +2 -2
  116. package/lib/module/components/listitems/ListItemSwitch.js.map +1 -1
  117. package/lib/module/components/listitems/ListItemTransaction.js +3 -3
  118. package/lib/module/components/listitems/ListItemTransaction.js.map +1 -1
  119. package/lib/module/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +7 -7
  120. package/lib/module/components/modules/ModuleAttachment.js +2 -2
  121. package/lib/module/components/modules/ModuleAttachment.js.map +1 -1
  122. package/lib/module/components/modules/ModuleCheckout.js +2 -2
  123. package/lib/module/components/modules/ModuleCheckout.js.map +1 -1
  124. package/lib/module/components/modules/ModuleCredential.js +2 -2
  125. package/lib/module/components/modules/ModuleCredential.js.map +1 -1
  126. package/lib/module/components/modules/ModuleNavigation.js +4 -3
  127. package/lib/module/components/modules/ModuleNavigation.js.map +1 -1
  128. package/lib/module/components/modules/ModulePaymentNotice.js +3 -3
  129. package/lib/module/components/modules/ModulePaymentNotice.js.map +1 -1
  130. package/lib/module/components/modules/ModuleSummary.js +2 -2
  131. package/lib/module/components/modules/ModuleSummary.js.map +1 -1
  132. package/lib/module/components/otpInput/BoxedInput.js +5 -7
  133. package/lib/module/components/otpInput/BoxedInput.js.map +1 -1
  134. package/lib/module/components/otpInput/OTPInput.js +5 -4
  135. package/lib/module/components/otpInput/OTPInput.js.map +1 -1
  136. package/lib/module/components/tabs/TabItem.js +2 -2
  137. package/lib/module/components/tabs/TabItem.js.map +1 -1
  138. package/lib/module/components/textInput/TextInputBase.js +3 -3
  139. package/lib/module/components/textInput/TextInputBase.js.map +1 -1
  140. package/lib/module/components/tooltip/Arrows.js +36 -0
  141. package/lib/module/components/tooltip/Arrows.js.map +1 -0
  142. package/lib/module/components/tooltip/Tooltip.js +165 -0
  143. package/lib/module/components/tooltip/Tooltip.js.map +1 -0
  144. package/lib/module/components/tooltip/index.js +2 -0
  145. package/lib/module/components/tooltip/index.js.map +1 -0
  146. package/lib/module/components/tooltip/styles.js +43 -0
  147. package/lib/module/components/tooltip/styles.js.map +1 -0
  148. package/lib/module/components/tooltip/utils/index.js +163 -0
  149. package/lib/module/components/tooltip/utils/index.js.map +1 -0
  150. package/lib/module/components/tooltip/utils/types.js +2 -0
  151. package/lib/module/components/tooltip/utils/types.js.map +1 -0
  152. package/lib/module/components/typography/{LabelSmall.js → BodySmall.js} +6 -8
  153. package/lib/module/components/typography/BodySmall.js.map +1 -0
  154. package/lib/module/components/typography/ButtonText.js +1 -3
  155. package/lib/module/components/typography/ButtonText.js.map +1 -1
  156. package/lib/module/components/typography/H3.js +3 -6
  157. package/lib/module/components/typography/H3.js.map +1 -1
  158. package/lib/module/components/typography/H6.js +4 -5
  159. package/lib/module/components/typography/H6.js.map +1 -1
  160. package/lib/module/components/typography/__test__/__snapshots__/typography.test.tsx.snap +118 -161
  161. package/lib/module/components/typography/__test__/typography.test.js +6 -18
  162. package/lib/module/components/typography/__test__/typography.test.js.map +1 -1
  163. package/lib/module/components/typography/index.js +6 -10
  164. package/lib/module/components/typography/index.js.map +1 -1
  165. package/lib/typescript/components/alert/Alert.d.ts.map +1 -1
  166. package/lib/typescript/components/banner/Banner.d.ts +1 -1
  167. package/lib/typescript/components/banner/Banner.d.ts.map +1 -1
  168. package/lib/typescript/components/featureInfo/FeatureInfo.d.ts.map +1 -1
  169. package/lib/typescript/components/index.d.ts +1 -0
  170. package/lib/typescript/components/index.d.ts.map +1 -1
  171. package/lib/typescript/components/layout/HeaderFirstLevel.d.ts.map +1 -1
  172. package/lib/typescript/components/listitems/ListItemSwitch.d.ts.map +1 -1
  173. package/lib/typescript/components/modules/ModuleNavigation.d.ts.map +1 -1
  174. package/lib/typescript/components/otpInput/BoxedInput.d.ts.map +1 -1
  175. package/lib/typescript/components/otpInput/OTPInput.d.ts.map +1 -1
  176. package/lib/typescript/components/tooltip/Arrows.d.ts +14 -0
  177. package/lib/typescript/components/tooltip/Arrows.d.ts.map +1 -0
  178. package/lib/typescript/components/tooltip/Tooltip.d.ts +64 -0
  179. package/lib/typescript/components/tooltip/Tooltip.d.ts.map +1 -0
  180. package/lib/typescript/components/tooltip/index.d.ts +2 -0
  181. package/lib/typescript/components/tooltip/index.d.ts.map +1 -0
  182. package/lib/typescript/components/tooltip/styles.d.ts +41 -0
  183. package/lib/typescript/components/tooltip/styles.d.ts.map +1 -0
  184. package/lib/typescript/components/tooltip/utils/index.d.ts +89 -0
  185. package/lib/typescript/components/tooltip/utils/index.d.ts.map +1 -0
  186. package/lib/typescript/components/tooltip/utils/types.d.ts +10 -0
  187. package/lib/typescript/components/tooltip/utils/types.d.ts.map +1 -0
  188. package/lib/typescript/components/typography/Body.d.ts +1 -1
  189. package/lib/typescript/components/typography/Body.d.ts.map +1 -1
  190. package/lib/typescript/components/typography/BodySmall.d.ts +13 -0
  191. package/lib/typescript/components/typography/BodySmall.d.ts.map +1 -0
  192. package/lib/typescript/components/typography/ButtonText.d.ts.map +1 -1
  193. package/lib/typescript/components/typography/H3.d.ts +2 -0
  194. package/lib/typescript/components/typography/H3.d.ts.map +1 -1
  195. package/lib/typescript/components/typography/H6.d.ts.map +1 -1
  196. package/lib/typescript/components/typography/LabelMini.d.ts +1 -1
  197. package/lib/typescript/components/typography/LabelMini.d.ts.map +1 -1
  198. package/lib/typescript/components/typography/index.d.ts +6 -10
  199. package/lib/typescript/components/typography/index.d.ts.map +1 -1
  200. package/package.json +1 -1
  201. package/src/components/alert/Alert.tsx +3 -4
  202. package/src/components/alert/AlertEdgeToEdge.tsx +3 -3
  203. package/src/components/banner/Banner.tsx +7 -5
  204. package/src/components/banner/__test__/__snapshots__/banner.test.tsx.snap +2 -2
  205. package/src/components/buttons/ButtonLink.tsx +1 -1
  206. package/src/components/buttons/ButtonOutline.tsx +1 -1
  207. package/src/components/buttons/__test__/__snapshots__/button.test.tsx.snap +3 -3
  208. package/src/components/featureInfo/FeatureInfo.tsx +6 -6
  209. package/src/components/index.tsx +1 -0
  210. package/src/components/layout/HeaderFirstLevel.tsx +1 -0
  211. package/src/components/listitems/ListItemCheckbox.tsx +3 -3
  212. package/src/components/listitems/ListItemInfo.tsx +3 -3
  213. package/src/components/listitems/ListItemInfoCopy.tsx +3 -3
  214. package/src/components/listitems/ListItemNav.tsx +3 -3
  215. package/src/components/listitems/ListItemNavAlert.tsx +3 -3
  216. package/src/components/listitems/ListItemRadio.tsx +3 -3
  217. package/src/components/listitems/ListItemRadioWithAmount.tsx +5 -5
  218. package/src/components/listitems/ListItemSwitch.tsx +4 -4
  219. package/src/components/listitems/ListItemTransaction.tsx +5 -5
  220. package/src/components/listitems/__test__/__snapshots__/listitem.test.tsx.snap +7 -7
  221. package/src/components/modules/ModuleAttachment.tsx +3 -3
  222. package/src/components/modules/ModuleCheckout.tsx +3 -3
  223. package/src/components/modules/ModuleCredential.tsx +3 -3
  224. package/src/components/modules/ModuleNavigation.tsx +6 -4
  225. package/src/components/modules/ModulePaymentNotice.tsx +5 -5
  226. package/src/components/modules/ModuleSummary.tsx +3 -3
  227. package/src/components/otpInput/BoxedInput.tsx +6 -5
  228. package/src/components/otpInput/OTPInput.tsx +23 -8
  229. package/src/components/tabs/TabItem.tsx +3 -3
  230. package/src/components/textInput/TextInputBase.tsx +5 -5
  231. package/src/components/tooltip/Arrows.tsx +36 -0
  232. package/src/components/tooltip/Tooltip.tsx +313 -0
  233. package/src/components/tooltip/index.ts +1 -0
  234. package/src/components/tooltip/styles.ts +44 -0
  235. package/src/components/tooltip/utils/index.ts +179 -0
  236. package/src/components/tooltip/utils/types.ts +9 -0
  237. package/src/components/typography/Body.tsx +1 -1
  238. package/src/components/typography/{LabelSmall.tsx → BodySmall.tsx} +7 -14
  239. package/src/components/typography/ButtonText.tsx +2 -4
  240. package/src/components/typography/H3.tsx +11 -8
  241. package/src/components/typography/H6.tsx +5 -6
  242. package/src/components/typography/LabelMini.tsx +1 -1
  243. package/src/components/typography/__test__/__snapshots__/typography.test.tsx.snap +118 -161
  244. package/src/components/typography/__test__/typography.test.tsx +8 -24
  245. package/src/components/typography/index.tsx +6 -10
  246. package/lib/commonjs/components/typography/BaseTypography.js +0 -52
  247. package/lib/commonjs/components/typography/BaseTypography.js.map +0 -1
  248. package/lib/commonjs/components/typography/Chip.js +0 -41
  249. package/lib/commonjs/components/typography/Chip.js.map +0 -1
  250. package/lib/commonjs/components/typography/Factory.js +0 -62
  251. package/lib/commonjs/components/typography/Factory.js.map +0 -1
  252. package/lib/commonjs/components/typography/Label.js +0 -51
  253. package/lib/commonjs/components/typography/Label.js.map +0 -1
  254. package/lib/commonjs/components/typography/LabelSmall.js.map +0 -1
  255. package/lib/module/components/typography/BaseTypography.js +0 -44
  256. package/lib/module/components/typography/BaseTypography.js.map +0 -1
  257. package/lib/module/components/typography/Chip.js +0 -32
  258. package/lib/module/components/typography/Chip.js.map +0 -1
  259. package/lib/module/components/typography/Factory.js +0 -55
  260. package/lib/module/components/typography/Factory.js.map +0 -1
  261. package/lib/module/components/typography/Label.js +0 -42
  262. package/lib/module/components/typography/Label.js.map +0 -1
  263. package/lib/module/components/typography/LabelSmall.js.map +0 -1
  264. package/lib/typescript/components/typography/BaseTypography.d.ts +0 -29
  265. package/lib/typescript/components/typography/BaseTypography.d.ts.map +0 -1
  266. package/lib/typescript/components/typography/Chip.d.ts +0 -13
  267. package/lib/typescript/components/typography/Chip.d.ts.map +0 -1
  268. package/lib/typescript/components/typography/Factory.d.ts +0 -43
  269. package/lib/typescript/components/typography/Factory.d.ts.map +0 -1
  270. package/lib/typescript/components/typography/Label.d.ts +0 -13
  271. package/lib/typescript/components/typography/Label.d.ts.map +0 -1
  272. package/lib/typescript/components/typography/LabelSmall.d.ts +0 -13
  273. package/lib/typescript/components/typography/LabelSmall.d.ts.map +0 -1
  274. package/src/components/typography/BaseTypography.tsx +0 -71
  275. package/src/components/typography/Chip.tsx +0 -33
  276. package/src/components/typography/Factory.tsx +0 -98
  277. package/src/components/typography/Label.tsx +0 -62
@@ -0,0 +1,313 @@
1
+ import React, {
2
+ useState,
3
+ useRef,
4
+ PropsWithChildren,
5
+ useEffect,
6
+ useCallback,
7
+ JSXElementConstructor,
8
+ useMemo,
9
+ ReactElement
10
+ } from "react";
11
+ import {
12
+ View,
13
+ Modal,
14
+ Dimensions,
15
+ LayoutChangeEvent,
16
+ TouchableWithoutFeedback
17
+ } from "react-native";
18
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
19
+ import { every, some } from "lodash";
20
+ import { IOColors } from "../../core";
21
+ import { Body, H6 } from "../typography";
22
+ import { IconButton } from "../buttons";
23
+ import { BottomArrow, LeftArrow, RightArrow, TopArrow } from "./Arrows";
24
+ import {
25
+ ARROW_HEIGHT,
26
+ EMPTY_SPACE,
27
+ getArrowBoxByPlacement,
28
+ getArrowCoords,
29
+ getArrowVerticalAlignment,
30
+ getDisplayInsets,
31
+ getTooltipCoords,
32
+ getTooltipVerticalAlignment,
33
+ isDefined,
34
+ isNotZero
35
+ } from "./utils";
36
+ import { getChildrenPosition, tooltipStyles } from "./styles";
37
+ import {
38
+ ChildrenCoords,
39
+ DisplayInsets,
40
+ Placement,
41
+ TooltipLayout
42
+ } from "./utils/types";
43
+
44
+ const screenDimensions = Dimensions.get("window");
45
+ const INITIAL_COORDS: ChildrenCoords = {
46
+ x: 0,
47
+ y: 0,
48
+ width: 0,
49
+ height: 0
50
+ };
51
+ const ARROWS_BY_PLACEMENT: Record<
52
+ Placement,
53
+ JSXElementConstructor<{ color: string }>
54
+ > = {
55
+ top: TopArrow,
56
+ bottom: BottomArrow,
57
+ left: LeftArrow,
58
+ right: RightArrow
59
+ };
60
+
61
+ type CommonProps = {
62
+ /**
63
+ * The title text displayed at the top of the tooltip.
64
+ */
65
+ title: string;
66
+ /**
67
+ * The tooltip text content.
68
+ */
69
+ content: string;
70
+ /**
71
+ * Controls the visibility of the tooltip.
72
+ */
73
+ isVisible: boolean;
74
+ /**
75
+ * Initial tooltip position; can be 'top', 'bottom', 'left', or 'right'.
76
+ * @default top
77
+ */
78
+ placement?: Placement;
79
+ /**
80
+ * Insets for adjusting tooltip position within screen boundaries.
81
+ * @default {}
82
+ */
83
+ displayInsets?: Partial<DisplayInsets>;
84
+ /**
85
+ * Accessibility label for the close icon button.
86
+ */
87
+ closeIconAccessibilityLabel: string;
88
+ /**
89
+ * Determines whether interactions with the tooltip's children are allowed when `isVisible` is set to true.
90
+ * @default false
91
+ */
92
+ childrenInteractionsEnabled?: boolean;
93
+ /**
94
+ * Callback function triggered when the tooltip is closed.
95
+ */
96
+ onClose: () => void;
97
+ };
98
+ type CloseWithTapOnBackground = {
99
+ /**
100
+ * Allows closing the tooltip by tapping outside of it.
101
+ */
102
+ allowCloseOnBackgroundTap: true;
103
+ /**
104
+ * Accessibility label for the tooltip background mask.
105
+ */
106
+ backgroundAccessibilityLabel: string;
107
+ };
108
+ type CloseWithBackgroundTapDisabled = {
109
+ allowCloseOnBackgroundTap?: false;
110
+ };
111
+ type Props = CommonProps & (CloseWithTapOnBackground | CloseWithBackgroundTapDisabled);
112
+
113
+ /**
114
+ * Tooltip component that displays a contextual tooltip around its children.
115
+ * The tooltip position is controlled by the `placement` prop and can adjust
116
+ * dynamically if there is insufficient space.
117
+ * @param {Props} props - The component props
118
+ *
119
+ * @returns {ReactElement} A tooltip component rendered around the specified children.
120
+ */
121
+ export const Tooltip = ({
122
+ children,
123
+ title,
124
+ content,
125
+ placement: initialPlacement = "top",
126
+ closeIconAccessibilityLabel,
127
+ isVisible,
128
+ displayInsets = {},
129
+ allowCloseOnBackgroundTap,
130
+ childrenInteractionsEnabled = false,
131
+ onClose
132
+ }: PropsWithChildren<Props>): ReactElement => {
133
+ const insets = useSafeAreaInsets();
134
+ const [currentPlacement, setCurrentPlacement] =
135
+ useState<Placement>(initialPlacement);
136
+ const [childrenCoords, setChildrenCoords] = useState<ChildrenCoords>(INITIAL_COORDS);
137
+ const [tooltipLayout, setTooltipLayout] = useState<TooltipLayout>();
138
+ const childRef = useRef<View>(null);
139
+ const titleRef = useRef<View>(null);
140
+ const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
141
+
142
+ const Arrow = useMemo(
143
+ () => ARROWS_BY_PLACEMENT[currentPlacement],
144
+ [currentPlacement]
145
+ );
146
+ const isChildrenMeasurementFinished =
147
+ every(childrenCoords, isDefined)
148
+ && some(childrenCoords, isNotZero);
149
+ const isTooltipMeasurementCompleted = isDefined(tooltipLayout);
150
+ const tooltipVisibility = { opacity: isTooltipMeasurementCompleted ? 1 : 0 };
151
+
152
+ /**
153
+ * This function sets the `Tooltip` children coordinates
154
+ */
155
+ const measureChildrenCoords = useCallback(() => {
156
+ if (childRef.current && typeof childRef.current.measure === "function") {
157
+ childRef.current.measure((_, __, width, height, px, py) => {
158
+ const coords = {
159
+ x: px,
160
+ y: py,
161
+ width,
162
+ height
163
+ };
164
+ if (every(coords, isDefined)) {
165
+ setChildrenCoords(coords);
166
+ }
167
+ });
168
+ }
169
+ }, []);
170
+
171
+ useEffect(() => {
172
+ if (isVisible) {
173
+ // A new measure is executed every time the `Tooltip` is visible
174
+ // This is required for use within ScrollView components.
175
+ // eslint-disable-next-line functional/immutable-data
176
+ timeoutRef.current = setTimeout(measureChildrenCoords, 100);
177
+ } else {
178
+ setChildrenCoords(INITIAL_COORDS);
179
+ setCurrentPlacement(initialPlacement);
180
+ }
181
+
182
+ return () => {
183
+ if (isVisible) {
184
+ clearTimeout(timeoutRef.current);
185
+ }
186
+ };
187
+ }, [isVisible, initialPlacement, measureChildrenCoords]);
188
+
189
+ /**
190
+ * This function works with `top` and `bottom` placement and sets the current placement to their opposite value
191
+ * if in the selected one there is no space to prompt the tooltip
192
+ */
193
+ const invertPlacementIfNeeded = useCallback(
194
+ (nativeEvent: LayoutChangeEvent["nativeEvent"]) => {
195
+ if (initialPlacement === "top") {
196
+ const hasSpace = nativeEvent.layout.y >= insets.top;
197
+
198
+ if (!hasSpace) {
199
+ setCurrentPlacement("bottom");
200
+ }
201
+ }
202
+ if (initialPlacement === "bottom") {
203
+ const remainingSpace =
204
+ screenDimensions.height - nativeEvent.layout.y - insets.bottom;
205
+ const tooltipMinHeight =
206
+ nativeEvent.layout.height + ARROW_HEIGHT + EMPTY_SPACE;
207
+ const hasSpace = remainingSpace >= tooltipMinHeight;
208
+
209
+ if (!hasSpace) {
210
+ setCurrentPlacement("top");
211
+ }
212
+ }
213
+ },
214
+ [insets.bottom, insets.top, initialPlacement]
215
+ );
216
+
217
+ const handleTooltipOnLayout = useCallback(
218
+ ({ nativeEvent }: LayoutChangeEvent) => {
219
+ invertPlacementIfNeeded(nativeEvent);
220
+ setTooltipLayout(nativeEvent.layout);
221
+ },
222
+ [invertPlacementIfNeeded]
223
+ );
224
+
225
+ const handleTapOnBackground = useCallback(() => {
226
+ if (allowCloseOnBackgroundTap) {
227
+ onClose();
228
+ }
229
+ }, [allowCloseOnBackgroundTap, onClose]);
230
+
231
+ return (
232
+ <>
233
+ <View
234
+ // This prop is necessary for .measure to work correctly, as explained here: https://github.com/facebook/react-native/issues/29712
235
+ collapsable={false}
236
+ ref={childRef}
237
+ >
238
+ {children}
239
+ </View>
240
+ <Modal transparent visible={isVisible && isChildrenMeasurementFinished}>
241
+ <View
242
+ accessibilityElementsHidden={!childrenInteractionsEnabled}
243
+ importantForAccessibility={childrenInteractionsEnabled ? 'auto' : 'no-hide-descendants'}
244
+ pointerEvents={childrenInteractionsEnabled ? "auto" : "box-only"}
245
+ style={[
246
+ tooltipStyles.childrenContainer,
247
+ getChildrenPosition(childrenCoords)
248
+ ]}
249
+ >
250
+ {children}
251
+ </View>
252
+ <TouchableWithoutFeedback
253
+ accessible={allowCloseOnBackgroundTap}
254
+ accessibilityRole={allowCloseOnBackgroundTap ? "button" : "none"}
255
+ importantForAccessibility={allowCloseOnBackgroundTap ? 'yes' : 'no'}
256
+ accessibilityElementsHidden={!allowCloseOnBackgroundTap}
257
+ onPress={handleTapOnBackground}
258
+ >
259
+ <View
260
+ style={[
261
+ tooltipStyles.overlay,
262
+ { height: screenDimensions.height }
263
+ ]}
264
+ />
265
+ </TouchableWithoutFeedback>
266
+ <View
267
+ onLayout={handleTooltipOnLayout}
268
+ style={[
269
+ tooltipStyles.tooltipContainer,
270
+ getTooltipCoords(
271
+ currentPlacement,
272
+ childrenCoords,
273
+ getDisplayInsets(displayInsets),
274
+ screenDimensions
275
+ ),
276
+ getTooltipVerticalAlignment(
277
+ currentPlacement,
278
+ childrenCoords.height,
279
+ tooltipLayout?.height
280
+ ),
281
+ tooltipVisibility
282
+ ]}
283
+ >
284
+ <H6 ref={titleRef}>{title}</H6>
285
+ <View style={tooltipStyles.closeIcon}>
286
+ <IconButton
287
+ color="neutral"
288
+ icon="closeSmall"
289
+ accessibilityLabel={closeIconAccessibilityLabel}
290
+ onPress={onClose}
291
+ />
292
+ </View>
293
+ <Body>{content}</Body>
294
+ </View>
295
+ <View
296
+ style={[
297
+ tooltipStyles.arrowContainer,
298
+ getArrowBoxByPlacement(currentPlacement),
299
+ getArrowCoords(
300
+ currentPlacement,
301
+ childrenCoords,
302
+ screenDimensions
303
+ ),
304
+ getArrowVerticalAlignment(currentPlacement, childrenCoords.height),
305
+ tooltipVisibility
306
+ ]}
307
+ >
308
+ <Arrow color={IOColors.white} />
309
+ </View>
310
+ </Modal>
311
+ </>
312
+ );
313
+ };
@@ -0,0 +1 @@
1
+ export * from "./Tooltip";
@@ -0,0 +1,44 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { IOColors } from '../../core';
3
+ import { ChildrenCoords } from './utils/types';
4
+
5
+ export const tooltipStyles = StyleSheet.create({
6
+ overlay: {
7
+ position: "absolute",
8
+ width: "100%",
9
+ height: "100%",
10
+ backgroundColor: IOColors["grey-850"],
11
+ opacity: 0.6,
12
+ zIndex: 997
13
+ },
14
+ childrenContainer: {
15
+ position: "absolute",
16
+ zIndex: 1000
17
+ },
18
+ tooltipContainer: {
19
+ position: "absolute",
20
+ paddingHorizontal: 16,
21
+ paddingVertical: 16,
22
+ backgroundColor: IOColors.white,
23
+ borderRadius: 8,
24
+ zIndex: 2000,
25
+ overflow: "visible"
26
+ },
27
+ arrowContainer: {
28
+ position: "absolute",
29
+ display: 'flex',
30
+ zIndex: 3000
31
+ },
32
+ closeIcon: {
33
+ position: 'absolute',
34
+ right: 8,
35
+ top: 9 // It's been used `9` instead of `8` to fix accessibility focus order. In this way title is read before close icon.
36
+ }
37
+ });
38
+
39
+ export const getChildrenPosition = (childrenCoords: ChildrenCoords) => ({
40
+ top: childrenCoords.y,
41
+ left: childrenCoords.x,
42
+ width: childrenCoords.width,
43
+ height: childrenCoords.height
44
+ });
@@ -0,0 +1,179 @@
1
+ import { ScaledSize } from 'react-native';
2
+ import { IOVisualCostants } from '../../../core';
3
+ import { ChildrenCoords, DisplayInsets, Placement } from './types';
4
+
5
+ export const ARROW_WIDTH = 24;
6
+ export const ARROW_HEIGHT = 14;
7
+ export const EMPTY_SPACE = 8;
8
+ const DEFAULT_INSETS: DisplayInsets = {
9
+ top: 0,
10
+ bottom: 0,
11
+ left: IOVisualCostants.appMarginDefault,
12
+ right: IOVisualCostants.appMarginDefault,
13
+ };
14
+
15
+ /**
16
+ * @param displayInsets custom display insets
17
+ * @returns An `object` based on `DEFAULT_INSETS` and `displayInsets`
18
+ */
19
+ export const getDisplayInsets = (
20
+ displayInsets: Partial<DisplayInsets>
21
+ ): DisplayInsets => ({ ...DEFAULT_INSETS, ...displayInsets });
22
+
23
+ /**
24
+ *
25
+ * @param placement The `Tooltip` placement
26
+ * @returns The `Arrow` box `width` and `height` based on `placement` value
27
+ */
28
+ export const getArrowBoxByPlacement = (placement: Placement) => {
29
+ switch (placement) {
30
+ case 'left':
31
+ case 'right':
32
+ return {
33
+ width: ARROW_HEIGHT,
34
+ height: ARROW_WIDTH,
35
+ };
36
+ default:
37
+ return {
38
+ height: ARROW_HEIGHT,
39
+ width: ARROW_WIDTH,
40
+ };
41
+ }
42
+ };
43
+
44
+ /**
45
+ * A utility function to calculate the `Tooltip` coordinates and dimensions
46
+ * @param placement The `Tooltip` placement in relation of its children
47
+ * @param childrenCoords The measures in screen of the `Tooltip` children
48
+ * @param displayInsets The active display insets
49
+ * @param screenDimensions The dimensions of the device screen
50
+ * @returns The `Tooltip` coordinates
51
+ */
52
+ export const getTooltipCoords = (
53
+ placement: Placement,
54
+ childrenCoords: ChildrenCoords,
55
+ displayInsets: DisplayInsets,
56
+ screenDimensions: ScaledSize
57
+ ) => {
58
+ const { width: screenWidth, height: screenHeight } = screenDimensions;
59
+
60
+ switch (placement) {
61
+ case "top":
62
+ return {
63
+ bottom: screenHeight - childrenCoords.y + ARROW_HEIGHT + EMPTY_SPACE,
64
+ left: displayInsets.left,
65
+ width: screenWidth - displayInsets.left - displayInsets.right
66
+ };
67
+ case "bottom":
68
+ return {
69
+ top: childrenCoords.y + childrenCoords.height + ARROW_HEIGHT + EMPTY_SPACE,
70
+ left: displayInsets.left,
71
+ width: screenWidth - displayInsets.left - displayInsets.right
72
+ };
73
+ case "left":
74
+ return {
75
+ top: childrenCoords.y,
76
+ left: displayInsets.left,
77
+ width:
78
+ screenWidth - (screenWidth - childrenCoords.x) - ARROW_HEIGHT - displayInsets.left - EMPTY_SPACE
79
+ };
80
+ case "right":
81
+ const elementSize = childrenCoords.width + childrenCoords.x + ARROW_HEIGHT + EMPTY_SPACE;
82
+
83
+ return {
84
+ top: childrenCoords.y,
85
+ left: elementSize,
86
+ width:
87
+ screenWidth -
88
+ (elementSize + displayInsets.right)
89
+ };
90
+ // TODO: provide a default center position in case of Tooltip without children
91
+ default:
92
+ return {};
93
+ }
94
+ };
95
+
96
+ /**
97
+ * A utility function to calculate the `Tooltip`'s `Arrow` coordinates
98
+ * @param placement The `Arrow` placement in relation of the `Tooltip` children
99
+ * @param childrenCoords The measures in screen of the `Tooltip` children
100
+ * @param screenDimensions The active display insets
101
+ * @returns The `Tooltip`'s Arrow coordinates
102
+ */
103
+ export const getArrowCoords = (
104
+ placement: Placement,
105
+ childrenCoords: ChildrenCoords,
106
+ screenDimensions: ScaledSize
107
+ ) => {
108
+ const { width: screenWidth, height: screenHeight } = screenDimensions;
109
+
110
+ switch (placement) {
111
+ case "top":
112
+ return {
113
+ bottom: screenHeight - childrenCoords.y + EMPTY_SPACE,
114
+ left: childrenCoords.x + childrenCoords.width / 2 - ARROW_WIDTH / 2
115
+ };
116
+ case "bottom":
117
+ return {
118
+ top: childrenCoords.y + childrenCoords.height + EMPTY_SPACE,
119
+ left: childrenCoords.x + childrenCoords.width / 2 - ARROW_WIDTH / 2
120
+ };
121
+ case "left":
122
+ return {
123
+ top: childrenCoords.y,
124
+ left: screenWidth - (screenWidth - childrenCoords.x) - ARROW_HEIGHT - EMPTY_SPACE - 1, // FIXME -> This `-1` is necessary because of the Svg size doesn't match the box size
125
+ };
126
+ case "right":
127
+ return {
128
+ top: childrenCoords.y,
129
+ left: childrenCoords.width + childrenCoords.x + EMPTY_SPACE
130
+ };
131
+ default:
132
+ // TODO: provide a default center position in case of Tooltip without children
133
+ return {};
134
+ }
135
+ };
136
+
137
+ /**
138
+ * A utility function to calculate the `Tooltip` vertical alignment
139
+ * @param placement The `Tooltip` placement in relation of its children
140
+ * @param childrenHeight The `Tooltip`'s children height
141
+ * @param tooltipHeight The `Tooltip`'s height
142
+ * @returns If placement is `left` or `right` it returns the vertical tranlsation to align the `Tooltip` center with its `children` center,
143
+ * otherwise `null` is returned
144
+ */
145
+ export const getTooltipVerticalAlignment = (placement: Placement, childrenHeight: number, tooltipHeight?: number) => {
146
+ if ((placement === "left" || placement === "right") && tooltipHeight) {
147
+ return {
148
+ transform: [
149
+ {
150
+ translateY:
151
+ -tooltipHeight / 2 + childrenHeight / 2
152
+ }
153
+ ]
154
+ };
155
+ }
156
+ return null;
157
+ };
158
+
159
+ /**
160
+ * A utility function to calculate the `Arrow` vertical alignment
161
+ * @param placement The `Tooltip` placement in relation of its children
162
+ * @param childrenHeight The `Tooltip`'s children height
163
+ */
164
+ export const getArrowVerticalAlignment = (placement: Placement, childrenHeight: number) => {
165
+ if (placement === "left" || placement === "right") {
166
+ return {
167
+ transform: [
168
+ {
169
+ translateY:
170
+ -ARROW_WIDTH / 2 + childrenHeight / 2
171
+ }
172
+ ]
173
+ };
174
+ }
175
+ return null;
176
+ };
177
+
178
+ export const isDefined = <T>(v: T) => v !== undefined;
179
+ export const isNotZero = (v: number) => v !== 0;
@@ -0,0 +1,9 @@
1
+ export type DisplayInsets = Record<Placement, number>;
2
+ export type Placement = "top" | "bottom" | "left" | "right";
3
+ export type ChildrenCoords = {
4
+ x: number;
5
+ y: number;
6
+ width: number;
7
+ height: number;
8
+ };
9
+ export type TooltipLayout = ChildrenCoords;
@@ -10,7 +10,7 @@ import {
10
10
  } from "./IOText";
11
11
 
12
12
  type BodyStyleProps = TypographicStyleProps & {
13
- weight?: Extract<IOFontWeight, "Regular" | "Semibold" | "Bold">;
13
+ weight?: Extract<IOFontWeight, "Regular" | "Semibold">;
14
14
  } & TypographicStyleAsLinkProps;
15
15
 
16
16
  export const bodyFontSize = 16;
@@ -9,20 +9,17 @@ import {
9
9
  TypographicStyleProps
10
10
  } from "./IOText";
11
11
 
12
- type LabelSmallProps = TypographicStyleProps & {
13
- weight?: Extract<IOFontWeight, "Regular" | "Semibold" | "Bold">;
12
+ type BodySmallProps = TypographicStyleProps & {
13
+ weight?: Extract<IOFontWeight, "Regular" | "Semibold">;
14
14
  } & TypographicStyleAsLinkProps;
15
15
 
16
16
  const fontName: IOFontFamily = "Titillio";
17
- const fontWeight: IOFontWeight = "Semibold";
18
-
19
17
  const legacyFontName: IOFontFamily = "TitilliumSansPro";
20
- const legacyFontWeight: IOFontWeight = "Semibold";
21
18
 
22
19
  /**
23
- * `LabelSmall` typographic style
20
+ * `BodySmall` typographic style
24
21
  */
25
- export const LabelSmall = forwardRef<View, LabelSmallProps>(
22
+ export const BodySmall = forwardRef<View, BodySmallProps>(
26
23
  (
27
24
  { weight: customWeight, color: customColor, asLink, ...props },
28
25
  ref?: ForwardedRef<View>
@@ -34,15 +31,11 @@ export const LabelSmall = forwardRef<View, LabelSmallProps>(
34
31
  ? theme["interactiveElem-default"]
35
32
  : theme["textBody-tertiary"];
36
33
 
37
- const LabelSmallProps: IOTextProps = {
34
+ const BodySmallProps: IOTextProps = {
38
35
  ...props,
39
36
  dynamicTypeRamp: "footnote" /* iOS only */,
40
37
  font: isExperimental ? fontName : legacyFontName,
41
- weight: customWeight
42
- ? customWeight
43
- : isExperimental
44
- ? fontWeight
45
- : legacyFontWeight,
38
+ weight: customWeight ?? "Regular",
46
39
  size: 14,
47
40
  lineHeight: 21,
48
41
  color: customColor ?? defaultColor,
@@ -55,7 +48,7 @@ export const LabelSmall = forwardRef<View, LabelSmallProps>(
55
48
  };
56
49
 
57
50
  return (
58
- <IOText ref={ref} {...LabelSmallProps}>
51
+ <IOText ref={ref} {...BodySmallProps}>
59
52
  {props.children}
60
53
  </IOText>
61
54
  );
@@ -2,7 +2,7 @@ import React, { ForwardedRef, forwardRef } from "react";
2
2
  import { View } from "react-native";
3
3
  import { useIOExperimentalDesign } from "../../core";
4
4
  import { IOColors } from "../../core/IOColors";
5
- import { IOFontFamily, IOFontSize, IOFontWeight } from "../../utils/fonts";
5
+ import { IOFontFamily, IOFontSize } from "../../utils/fonts";
6
6
  import { IOText, IOTextProps, TypographicStyleProps } from "./IOText";
7
7
 
8
8
  export const buttonTextFontSize: IOFontSize = 16;
@@ -10,11 +10,9 @@ export const buttonTextFontSize: IOFontSize = 16;
10
10
  `AnimatedText` for color transition through Reanimated */
11
11
  const defaultColor: IOColors = "white";
12
12
  const fontName: IOFontFamily = "Titillio";
13
- const fontWeight: IOFontWeight = "Semibold";
14
13
 
15
14
  // TODO: Remove this when legacy look is deprecated https://pagopa.atlassian.net/browse/IOPLT-153
16
15
  const legacyFontName: IOFontFamily = "TitilliumSansPro";
17
- const legacyFontWeight: IOFontWeight = "Bold";
18
16
 
19
17
  /**
20
18
  * `ButtonText` typographic style
@@ -26,7 +24,7 @@ export const ButtonText = forwardRef<View, TypographicStyleProps>(
26
24
  const ButtonTextProps: IOTextProps = {
27
25
  ...props,
28
26
  font: isExperimental ? fontName : legacyFontName,
29
- weight: isExperimental ? fontWeight : legacyFontWeight,
27
+ weight: "Semibold",
30
28
  size: buttonTextFontSize,
31
29
  lineHeight: 20,
32
30
  color: customColor ?? defaultColor
@@ -1,26 +1,29 @@
1
1
  import React, { ForwardedRef, forwardRef } from "react";
2
2
  import { View } from "react-native";
3
- import { IOTheme, useIOExperimentalDesign, useIOTheme } from "../../core";
3
+ import { useIOExperimentalDesign, useIOTheme } from "../../core";
4
4
  import { IOFontFamily, IOFontSize, IOFontWeight } from "../../utils/fonts";
5
5
  import { IOText, IOTextProps, TypographicStyleProps } from "./IOText";
6
6
 
7
- const defaultColor: keyof IOTheme = "textHeading-default";
7
+ type H3StyleProps = TypographicStyleProps & {
8
+ weight?: Extract<IOFontWeight, "Semibold" | "Bold">;
9
+ };
8
10
 
9
11
  /* Common typographic styles */
10
12
  export const h3FontSize: IOFontSize = 22;
11
13
  export const h3LineHeight = 33;
12
14
  const fontName: IOFontFamily = "Titillio";
13
- const fontWeight: IOFontWeight = "Semibold";
14
15
 
15
16
  // TODO: Remove this when legacy look is deprecated https://pagopa.atlassian.net/browse/IOPLT-153
16
17
  const legacyFontName: IOFontFamily = "TitilliumSansPro";
17
- const legacyFontWeight: IOFontWeight = "Semibold";
18
18
 
19
19
  /**
20
20
  * `H3` typographic style
21
21
  */
22
- export const H3 = forwardRef<View, TypographicStyleProps>(
23
- ({ color: customColor, ...props }, ref?: ForwardedRef<View>) => {
22
+ export const H3 = forwardRef<View, H3StyleProps>(
23
+ (
24
+ { weight: customWeight, color: customColor, ...props },
25
+ ref?: ForwardedRef<View>
26
+ ) => {
24
27
  const theme = useIOTheme();
25
28
  const { isExperimental } = useIOExperimentalDesign();
26
29
 
@@ -28,10 +31,10 @@ export const H3 = forwardRef<View, TypographicStyleProps>(
28
31
  ...props,
29
32
  dynamicTypeRamp: "title2", // iOS only
30
33
  font: isExperimental ? fontName : legacyFontName,
31
- weight: isExperimental ? fontWeight : legacyFontWeight,
34
+ weight: customWeight ?? "Semibold",
32
35
  size: h3FontSize,
33
36
  lineHeight: h3LineHeight,
34
- color: customColor ?? theme[defaultColor]
37
+ color: customColor ?? theme["textHeading-default"]
35
38
  };
36
39
 
37
40
  return (