@telefonica/mistica 17.5.0 → 17.7.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 (289) hide show
  1. package/css/mistica.css +1 -1
  2. package/dist/accordion.css-mistica.js +6 -6
  3. package/dist/align.css-mistica.js +1 -1
  4. package/dist/autocomplete.css-mistica.js +1 -1
  5. package/dist/avatar.css-mistica.js +1 -1
  6. package/dist/badge.css-mistica.js +1 -1
  7. package/dist/box.css-mistica.js +13 -13
  8. package/dist/boxed.css-mistica.js +24 -24
  9. package/dist/button-group.css-mistica.js +1 -1
  10. package/dist/button-layout.css-mistica.js +14 -14
  11. package/dist/button.css-mistica.js +34 -34
  12. package/dist/callout.css-mistica.js +11 -11
  13. package/dist/card-cover.d.ts +2 -2
  14. package/dist/card-data.d.ts +2 -2
  15. package/dist/card-data.js +6 -8
  16. package/dist/card-internal.css-mistica.js +47 -29
  17. package/dist/card-internal.css.d.ts +4 -0
  18. package/dist/card-internal.d.ts +38 -3
  19. package/dist/card-internal.js +394 -301
  20. package/dist/card-media.d.ts +2 -2
  21. package/dist/card-media.js +7 -9
  22. package/dist/card-naked.d.ts +2 -2
  23. package/dist/card-naked.js +9 -11
  24. package/dist/carousel.css-mistica.js +8 -8
  25. package/dist/checkbox.css-mistica.js +11 -11
  26. package/dist/checkbox.d.ts +2 -0
  27. package/dist/checkbox.js +10 -10
  28. package/dist/chip.css-mistica.js +15 -15
  29. package/dist/circle.css-mistica.js +1 -1
  30. package/dist/community/advanced-data-card.css-mistica.js +20 -11
  31. package/dist/community/advanced-data-card.css.d.ts +2 -0
  32. package/dist/community/advanced-data-card.d.ts +7 -3
  33. package/dist/community/advanced-data-card.js +164 -142
  34. package/dist/community/ai-card.css-mistica.js +13 -13
  35. package/dist/community/ai-card.js +1 -1
  36. package/dist/community/blocks.css-mistica.js +1 -1
  37. package/dist/community/cyber/example-component.css-mistica.js +1 -1
  38. package/dist/community/example-component.css-mistica.js +2 -2
  39. package/dist/counter.css-mistica.js +1 -1
  40. package/dist/cover-hero.css-mistica.js +2 -2
  41. package/dist/credit-card-number-field.css-mistica.js +3 -3
  42. package/dist/date-field.css-mistica.js +1 -1
  43. package/dist/date-time-picker.css-mistica.js +1 -1
  44. package/dist/dialog.css-mistica.js +4 -4
  45. package/dist/divider.css-mistica.js +5 -5
  46. package/dist/double-field.css-mistica.js +2 -2
  47. package/dist/drawer.css-mistica.js +1 -1
  48. package/dist/empty-state-card.css-mistica.js +1 -1
  49. package/dist/empty-state.css-mistica.js +5 -5
  50. package/dist/fade-in.css-mistica.js +1 -1
  51. package/dist/fade-out.css-mistica.js +1 -1
  52. package/dist/feedback.css-mistica.js +1 -1
  53. package/dist/file-upload.css-mistica.js +7 -7
  54. package/dist/fixed-footer-layout.css-mistica.js +2 -2
  55. package/dist/form.css-mistica.js +1 -1
  56. package/dist/generated/mistica-icons/icon-document-information-filled.js +165 -0
  57. package/dist/generated/mistica-icons/icon-document-information-light.js +165 -0
  58. package/dist/generated/mistica-icons/icon-document-information-regular.js +165 -0
  59. package/dist/generated/mistica-icons/icon-internet-roaming-filled.js +159 -0
  60. package/dist/generated/mistica-icons/icon-internet-roaming-light.js +159 -0
  61. package/dist/generated/mistica-icons/icon-internet-roaming-regular.js +159 -0
  62. package/dist/generated/mistica-icons/icon-mobile-information-filled.js +165 -0
  63. package/dist/generated/mistica-icons/icon-mobile-information-light.js +173 -0
  64. package/dist/generated/mistica-icons/icon-mobile-information-regular.js +165 -0
  65. package/dist/generated/mistica-icons/icon-search-ai-filled.js +165 -0
  66. package/dist/generated/mistica-icons/icon-search-ai-light.js +165 -0
  67. package/dist/generated/mistica-icons/icon-search-ai-regular.js +165 -0
  68. package/dist/grid-layout.css-mistica.js +3 -3
  69. package/dist/grid.css-mistica.js +120 -120
  70. package/dist/header.css-mistica.js +1 -1
  71. package/dist/hero.css-mistica.js +2 -2
  72. package/dist/horizontal-scroll.css-mistica.js +1 -1
  73. package/dist/icon-button.css-mistica.js +53 -53
  74. package/dist/icons/icon-chevron.css-mistica.js +2 -2
  75. package/dist/icons/icon-error.css-mistica.js +1 -1
  76. package/dist/image.css-mistica.js +10 -10
  77. package/dist/index.d.ts +12 -0
  78. package/dist/index.js +48 -0
  79. package/dist/inline.css-mistica.js +11 -11
  80. package/dist/list.css-mistica.js +7 -7
  81. package/dist/loading-bar.css-mistica.js +1 -1
  82. package/dist/loading-screen.css-mistica.js +4 -4
  83. package/dist/logo.css-mistica.js +5 -5
  84. package/dist/menu.css-mistica.js +26 -24
  85. package/dist/menu.css.d.ts +2 -2
  86. package/dist/menu.d.ts +15 -3
  87. package/dist/menu.js +184 -162
  88. package/dist/mosaic.css-mistica.js +1 -1
  89. package/dist/navigation-bar.css-mistica.js +9 -9
  90. package/dist/navigation-breadcrumbs.css-mistica.js +1 -1
  91. package/dist/navigation-shared.css-mistica.js +9 -9
  92. package/dist/package-version.js +1 -1
  93. package/dist/pagination.css-mistica.js +18 -18
  94. package/dist/pin-field.css-mistica.js +1 -1
  95. package/dist/popover.css-mistica.js +1 -1
  96. package/dist/popover.d.ts +1 -0
  97. package/dist/progress-bar.css-mistica.js +6 -6
  98. package/dist/radio-button.css-mistica.js +19 -19
  99. package/dist/radio-button.d.ts +3 -1
  100. package/dist/radio-button.js +73 -72
  101. package/dist/rating.css-mistica.js +2 -2
  102. package/dist/responsive-layout.css-mistica.js +6 -6
  103. package/dist/screen-reader-only.css-mistica.js +1 -1
  104. package/dist/select.css-mistica.js +15 -15
  105. package/dist/sheet-action-row.css-mistica.js +1 -1
  106. package/dist/sheet-common.css-mistica.js +1 -1
  107. package/dist/sheet-info.css-mistica.js +1 -1
  108. package/dist/sidenav-bar-layout.css-mistica.js +1 -1
  109. package/dist/sidenav-bar.css-mistica.js +71 -71
  110. package/dist/sidenav-bar.js +55 -50
  111. package/dist/skeletons.css-mistica.js +6 -6
  112. package/dist/skins/skin-contract.css-mistica.js +738 -738
  113. package/dist/skip-link.css-mistica.js +1 -1
  114. package/dist/slider.css-mistica.js +18 -18
  115. package/dist/snackbar.css-mistica.js +4 -4
  116. package/dist/spinner.css-mistica.js +1 -1
  117. package/dist/square.css-mistica.js +1 -1
  118. package/dist/stack.css-mistica.js +5 -5
  119. package/dist/stacking-group.css-mistica.js +1 -1
  120. package/dist/stepper.css-mistica.js +2 -2
  121. package/dist/switch-component.css-mistica.js +35 -35
  122. package/dist/switch-component.d.ts +2 -0
  123. package/dist/switch-component.js +19 -18
  124. package/dist/table.css-mistica.js +9 -9
  125. package/dist/tabs.css-mistica.js +17 -17
  126. package/dist/tag.css-mistica.js +1 -1
  127. package/dist/text-field-base.css-mistica.js +16 -16
  128. package/dist/text-field-components.css-mistica.js +3 -3
  129. package/dist/text-link.css-mistica.js +6 -6
  130. package/dist/text.css-mistica.js +6 -6
  131. package/dist/timeline.css-mistica.js +9 -9
  132. package/dist/timer.css-mistica.js +6 -6
  133. package/dist/tooltip.css-mistica.js +1 -1
  134. package/dist/tooltip.d.ts +3 -1
  135. package/dist/tooltip.js +158 -147
  136. package/dist/touchable.css-mistica.js +1 -1
  137. package/dist/utils/aspect-ratio-support.css-mistica.js +2 -2
  138. package/dist/video.css-mistica.js +1 -1
  139. package/dist/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
  140. package/dist-es/accordion.css-mistica.js +6 -6
  141. package/dist-es/align.css-mistica.js +1 -1
  142. package/dist-es/autocomplete.css-mistica.js +1 -1
  143. package/dist-es/avatar.css-mistica.js +1 -1
  144. package/dist-es/badge.css-mistica.js +1 -1
  145. package/dist-es/box.css-mistica.js +13 -13
  146. package/dist-es/boxed.css-mistica.js +23 -23
  147. package/dist-es/button-group.css-mistica.js +1 -1
  148. package/dist-es/button-layout.css-mistica.js +14 -14
  149. package/dist-es/button.css-mistica.js +34 -34
  150. package/dist-es/callout.css-mistica.js +11 -11
  151. package/dist-es/card-data.js +10 -12
  152. package/dist-es/card-internal.css-mistica.js +25 -19
  153. package/dist-es/card-internal.js +482 -395
  154. package/dist-es/card-media.js +11 -13
  155. package/dist-es/card-naked.js +14 -16
  156. package/dist-es/carousel.css-mistica.js +8 -8
  157. package/dist-es/checkbox.css-mistica.js +11 -11
  158. package/dist-es/checkbox.js +19 -19
  159. package/dist-es/chip.css-mistica.js +15 -15
  160. package/dist-es/circle.css-mistica.js +1 -1
  161. package/dist-es/community/advanced-data-card.css-mistica.js +10 -7
  162. package/dist-es/community/advanced-data-card.js +214 -192
  163. package/dist-es/community/ai-card.css-mistica.js +4 -4
  164. package/dist-es/community/ai-card.js +1 -1
  165. package/dist-es/community/blocks.css-mistica.js +1 -1
  166. package/dist-es/community/cyber/example-component.css-mistica.js +1 -1
  167. package/dist-es/community/example-component.css-mistica.js +2 -2
  168. package/dist-es/counter.css-mistica.js +1 -1
  169. package/dist-es/cover-hero.css-mistica.js +2 -2
  170. package/dist-es/credit-card-number-field.css-mistica.js +3 -3
  171. package/dist-es/date-field.css-mistica.js +1 -1
  172. package/dist-es/date-time-picker.css-mistica.js +1 -1
  173. package/dist-es/dialog.css-mistica.js +4 -4
  174. package/dist-es/divider.css-mistica.js +5 -5
  175. package/dist-es/double-field.css-mistica.js +2 -2
  176. package/dist-es/drawer.css-mistica.js +1 -1
  177. package/dist-es/empty-state-card.css-mistica.js +1 -1
  178. package/dist-es/empty-state.css-mistica.js +5 -5
  179. package/dist-es/fade-in.css-mistica.js +1 -1
  180. package/dist-es/fade-out.css-mistica.js +1 -1
  181. package/dist-es/feedback.css-mistica.js +1 -1
  182. package/dist-es/file-upload.css-mistica.js +7 -7
  183. package/dist-es/fixed-footer-layout.css-mistica.js +2 -2
  184. package/dist-es/form.css-mistica.js +1 -1
  185. package/dist-es/generated/mistica-icons/icon-document-information-filled.js +115 -0
  186. package/dist-es/generated/mistica-icons/icon-document-information-light.js +115 -0
  187. package/dist-es/generated/mistica-icons/icon-document-information-regular.js +115 -0
  188. package/dist-es/generated/mistica-icons/icon-internet-roaming-filled.js +109 -0
  189. package/dist-es/generated/mistica-icons/icon-internet-roaming-light.js +109 -0
  190. package/dist-es/generated/mistica-icons/icon-internet-roaming-regular.js +109 -0
  191. package/dist-es/generated/mistica-icons/icon-mobile-information-filled.js +115 -0
  192. package/dist-es/generated/mistica-icons/icon-mobile-information-light.js +123 -0
  193. package/dist-es/generated/mistica-icons/icon-mobile-information-regular.js +115 -0
  194. package/dist-es/generated/mistica-icons/icon-search-ai-filled.js +115 -0
  195. package/dist-es/generated/mistica-icons/icon-search-ai-light.js +115 -0
  196. package/dist-es/generated/mistica-icons/icon-search-ai-regular.js +115 -0
  197. package/dist-es/grid-layout.css-mistica.js +3 -3
  198. package/dist-es/grid.css-mistica.js +120 -120
  199. package/dist-es/header.css-mistica.js +1 -1
  200. package/dist-es/hero.css-mistica.js +2 -2
  201. package/dist-es/horizontal-scroll.css-mistica.js +1 -1
  202. package/dist-es/icon-button.css-mistica.js +53 -53
  203. package/dist-es/icons/icon-chevron.css-mistica.js +2 -2
  204. package/dist-es/icons/icon-error.css-mistica.js +1 -1
  205. package/dist-es/image.css-mistica.js +4 -4
  206. package/dist-es/index.js +1501 -1489
  207. package/dist-es/inline.css-mistica.js +11 -11
  208. package/dist-es/list.css-mistica.js +7 -7
  209. package/dist-es/loading-bar.css-mistica.js +1 -1
  210. package/dist-es/loading-screen.css-mistica.js +4 -4
  211. package/dist-es/logo.css-mistica.js +5 -5
  212. package/dist-es/menu.css-mistica.js +14 -15
  213. package/dist-es/menu.js +238 -216
  214. package/dist-es/mosaic.css-mistica.js +1 -1
  215. package/dist-es/navigation-bar.css-mistica.js +9 -9
  216. package/dist-es/navigation-breadcrumbs.css-mistica.js +1 -1
  217. package/dist-es/navigation-shared.css-mistica.js +9 -9
  218. package/dist-es/package-version.js +1 -1
  219. package/dist-es/pagination.css-mistica.js +18 -18
  220. package/dist-es/pin-field.css-mistica.js +1 -1
  221. package/dist-es/popover.css-mistica.js +1 -1
  222. package/dist-es/progress-bar.css-mistica.js +6 -6
  223. package/dist-es/radio-button.css-mistica.js +19 -19
  224. package/dist-es/radio-button.js +91 -90
  225. package/dist-es/rating.css-mistica.js +2 -2
  226. package/dist-es/responsive-layout.css-mistica.js +6 -6
  227. package/dist-es/screen-reader-only.css-mistica.js +1 -1
  228. package/dist-es/select.css-mistica.js +15 -15
  229. package/dist-es/sheet-action-row.css-mistica.js +1 -1
  230. package/dist-es/sheet-common.css-mistica.js +1 -1
  231. package/dist-es/sheet-info.css-mistica.js +1 -1
  232. package/dist-es/sidenav-bar-layout.css-mistica.js +1 -1
  233. package/dist-es/sidenav-bar.css-mistica.js +71 -71
  234. package/dist-es/sidenav-bar.js +70 -65
  235. package/dist-es/skeletons.css-mistica.js +6 -6
  236. package/dist-es/skins/skin-contract.css-mistica.js +738 -738
  237. package/dist-es/skip-link.css-mistica.js +1 -1
  238. package/dist-es/slider.css-mistica.js +18 -18
  239. package/dist-es/snackbar.css-mistica.js +4 -4
  240. package/dist-es/spinner.css-mistica.js +1 -1
  241. package/dist-es/square.css-mistica.js +1 -1
  242. package/dist-es/stack.css-mistica.js +5 -5
  243. package/dist-es/stacking-group.css-mistica.js +1 -1
  244. package/dist-es/stepper.css-mistica.js +2 -2
  245. package/dist-es/style.css +1 -1
  246. package/dist-es/switch-component.css-mistica.js +35 -35
  247. package/dist-es/switch-component.js +34 -33
  248. package/dist-es/table.css-mistica.js +9 -9
  249. package/dist-es/tabs.css-mistica.js +17 -17
  250. package/dist-es/tag.css-mistica.js +1 -1
  251. package/dist-es/text-field-base.css-mistica.js +16 -16
  252. package/dist-es/text-field-components.css-mistica.js +3 -3
  253. package/dist-es/text-link.css-mistica.js +6 -6
  254. package/dist-es/text.css-mistica.js +6 -6
  255. package/dist-es/timeline.css-mistica.js +9 -9
  256. package/dist-es/timer.css-mistica.js +6 -6
  257. package/dist-es/tooltip.css-mistica.js +1 -1
  258. package/dist-es/tooltip.js +198 -187
  259. package/dist-es/touchable.css-mistica.js +1 -1
  260. package/dist-es/utils/aspect-ratio-support.css-mistica.js +2 -2
  261. package/dist-es/video.css-mistica.js +1 -1
  262. package/dist-es/vivinho-loading-animation/vivinho-loading-animation.css-mistica.js +1 -1
  263. package/doc/components.md +35 -0
  264. package/package.json +4 -3
  265. package/src/card-cover.tsx +2 -2
  266. package/src/card-data.tsx +3 -4
  267. package/src/card-internal.css.ts +36 -0
  268. package/src/card-internal.tsx +162 -9
  269. package/src/card-media.tsx +3 -4
  270. package/src/card-naked.tsx +3 -4
  271. package/src/checkbox.tsx +6 -1
  272. package/src/community/__screenshot_tests__/__image_snapshots__/ai-card-screenshot-test-tsx-ai-card-line-break-at-chars-1-snap.png +0 -0
  273. package/src/community/__screenshot_tests__/__image_snapshots__/ai-card-screenshot-test-tsx-ai-card-static-text-1-snap.png +0 -0
  274. package/src/community/__screenshot_tests__/ai-card-screenshot-test.tsx +28 -0
  275. package/src/community/__stories__/advanced-data-card-story.tsx +5 -0
  276. package/src/community/__type_tests__/advanced-data-card-type-test.tsx +3 -0
  277. package/src/community/advanced-data-card.css.ts +26 -1
  278. package/src/community/advanced-data-card.tsx +123 -73
  279. package/src/community/ai-card.tsx +3 -3
  280. package/src/index.tsx +12 -0
  281. package/src/menu.css.ts +5 -9
  282. package/src/menu.tsx +82 -64
  283. package/src/package-version.tsx +1 -1
  284. package/src/popover.tsx +1 -0
  285. package/src/radio-button.tsx +7 -1
  286. package/src/sidenav-bar.tsx +9 -2
  287. package/src/switch-component.tsx +7 -3
  288. package/src/tooltip.css.ts +1 -0
  289. package/src/tooltip.tsx +94 -90
@@ -6,6 +6,7 @@ https://github.com/storybookjs/storybook/issues/11980
6
6
 
7
7
  'use client';
8
8
  import * as React from 'react';
9
+ import classnames from 'classnames';
9
10
  import {debounce} from './utils/helpers';
10
11
  import {SPACE} from './utils/keys';
11
12
  import {useControlProps} from './form-context';
@@ -36,6 +37,7 @@ type PropsRender = {
36
37
  'aria-labelledby'?: string;
37
38
  'aria-label'?: string;
38
39
  dataAttributes?: DataAttributes;
40
+ className?: string;
39
41
  };
40
42
 
41
43
  type PropsChildren = {
@@ -49,6 +51,7 @@ type PropsChildren = {
49
51
  'aria-labelledby'?: string;
50
52
  'aria-label'?: string;
51
53
  dataAttributes?: DataAttributes;
54
+ className?: string;
52
55
  };
53
56
 
54
57
  const Switch = (props: PropsRender | PropsChildren): JSX.Element => {
@@ -155,15 +158,16 @@ const Switch = (props: PropsRender | PropsChildren): JSX.Element => {
155
158
  onKeyDown={disabled ? undefined : handleKeyDown}
156
159
  tabIndex={disabled ? undefined : 0}
157
160
  ref={focusableRef}
158
- className={
161
+ className={classnames(
159
162
  props.render
160
163
  ? disabled
161
164
  ? styles.containerDisabledFullWidth
162
165
  : styles.containerFullWidth
163
166
  : disabled
164
167
  ? styles.containerDisabled
165
- : styles.container
166
- }
168
+ : styles.container,
169
+ props.className
170
+ )}
167
171
  aria-disabled={disabled}
168
172
  aria-label={props['aria-label']}
169
173
  aria-labelledby={props['aria-label'] ? undefined : labelId}
@@ -53,6 +53,7 @@ export const contentContainer = style([
53
53
  overflow: 'hidden',
54
54
  }),
55
55
  {
56
+ overflowY: 'auto',
56
57
  minWidth: CONTENT_MIN_WIDTH - 2 * BORDER_SIZE, // border is not included in this container
57
58
  },
58
59
  ]);
package/src/tooltip.tsx CHANGED
@@ -6,7 +6,6 @@ import {Transition} from 'react-transition-group';
6
6
  import * as styles from './tooltip.css';
7
7
  import Stack from './stack';
8
8
  import {Text2} from './text';
9
- import {getCssVarValue} from './utils/dom';
10
9
  import {ESC, TAB} from './utils/keys';
11
10
  import {isTouchableDevice} from './utils/environment';
12
11
  import {isEqual} from './utils/helpers';
@@ -41,7 +40,9 @@ const TOOLTIP_ENTER_TRANSITION_DELAY_IN_MS = 500;
41
40
  const TOOLTIP_EXIT_TRANSITION_DURATION_IN_MS = 100;
42
41
  const ARROW_SIZE = 20;
43
42
  const TOOLTIP_OFFSET_FROM_TARGET = 6;
44
- const TOOLTIP_PADDING_FROM_TARGET = TOOLTIP_OFFSET_FROM_TARGET + ARROW_SIZE / 2 + 1;
43
+ const TOOLTIP_BORDER_SIZE = 1;
44
+ const TOOLTIP_PADDING_FROM_TARGET = TOOLTIP_OFFSET_FROM_TARGET + ARROW_SIZE / 2 + TOOLTIP_BORDER_SIZE;
45
+ const REFLECTED_POSITION = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'} as const;
45
46
 
46
47
  type Position = 'top' | 'bottom' | 'left' | 'right';
47
48
 
@@ -79,62 +80,36 @@ const getFinalPosition = (
79
80
  tooltip: HTMLElement | undefined | null,
80
81
  position: Position,
81
82
  windowHeight: number,
82
- windowWidth: number
83
+ windowWidth: number,
84
+ contentHeight?: number
83
85
  ): Position | undefined => {
84
86
  if (!targetRect || !tooltip) {
85
87
  return undefined;
86
88
  }
87
- const {top, bottom, left, right} = targetRect;
88
-
89
- const availableSpaceOnBottom = windowHeight - bottom;
90
- const availableSpaceOnRight = windowWidth - right;
91
- const availableSpaceOnTop = top;
92
- const availableSpaceOnLeft = left;
93
-
94
- const {width, height} = getElementDimensionsWithoutPadding(tooltip);
95
-
96
- const tooltipWidth = width + TOOLTIP_PADDING_FROM_TARGET;
97
- const tooltipHeight = height + TOOLTIP_PADDING_FROM_TARGET;
98
-
99
- const fitsHorizontal = tooltipWidth <= Math.max(availableSpaceOnLeft, availableSpaceOnRight);
100
- const fitsVertical = tooltipHeight <= Math.max(availableSpaceOnBottom, availableSpaceOnTop);
101
-
102
- if (!fitsVertical && !fitsHorizontal) {
103
- return undefined;
89
+ const availableSpace = {
90
+ top: targetRect.top,
91
+ bottom: windowHeight - targetRect.bottom,
92
+ left: targetRect.left,
93
+ right: windowWidth - targetRect.right,
94
+ };
95
+ const dimensions = getElementDimensionsWithoutPadding(tooltip);
96
+ const width = dimensions.width;
97
+ const height = contentHeight === undefined ? dimensions.height : contentHeight + 2 * TOOLTIP_BORDER_SIZE;
98
+ const size = (position === 'top' || position === 'bottom' ? height : width) + TOOLTIP_PADDING_FROM_TARGET;
99
+ const reflected = REFLECTED_POSITION[position];
100
+ const candidateFinalPosition =
101
+ availableSpace[position] < size && availableSpace[reflected] > availableSpace[position]
102
+ ? reflected
103
+ : position;
104
+
105
+ if (
106
+ (candidateFinalPosition === 'left' || candidateFinalPosition === 'right') &&
107
+ availableSpace[candidateFinalPosition] < size
108
+ ) {
109
+ return availableSpace.bottom > availableSpace.top ? 'bottom' : 'top';
104
110
  }
105
111
 
106
- switch (position) {
107
- case 'left':
108
- if (fitsHorizontal) {
109
- return tooltipWidth <= availableSpaceOnLeft ? 'left' : 'right';
110
- } else {
111
- return availableSpaceOnBottom > availableSpaceOnTop ? 'bottom' : 'top';
112
- }
113
-
114
- case 'right':
115
- if (fitsHorizontal) {
116
- return tooltipWidth <= availableSpaceOnRight ? 'right' : 'left';
117
- } else {
118
- return availableSpaceOnBottom > availableSpaceOnTop ? 'bottom' : 'top';
119
- }
120
-
121
- case 'top':
122
- if (fitsVertical) {
123
- return tooltipHeight <= availableSpaceOnTop ? 'top' : 'bottom';
124
- } else {
125
- return availableSpaceOnLeft > availableSpaceOnRight ? 'left' : 'right';
126
- }
127
-
128
- case 'bottom':
129
- if (fitsVertical) {
130
- return tooltipHeight <= availableSpaceOnBottom ? 'bottom' : 'top';
131
- } else {
132
- return availableSpaceOnLeft > availableSpaceOnRight ? 'left' : 'right';
133
- }
134
-
135
- default:
136
- return undefined;
137
- }
112
+ return candidateFinalPosition;
138
113
  };
139
114
 
140
115
  type Props = {
@@ -145,6 +120,7 @@ type Props = {
145
120
  targetStyle?: React.CSSProperties;
146
121
  title?: string;
147
122
  position?: Position;
123
+ alignment?: 'start' | 'middle' | 'end';
148
124
  width?: number;
149
125
  delay?: boolean;
150
126
  dataAttributes?: DataAttributes;
@@ -157,6 +133,7 @@ type BaseTooltipProps = {
157
133
  target: React.ReactNode;
158
134
  targetStyle?: React.CSSProperties;
159
135
  position?: Position;
136
+ alignment?: 'start' | 'middle' | 'end';
160
137
  width?: number;
161
138
  delay?: boolean;
162
139
  dataAttributes?: DataAttributes;
@@ -174,6 +151,7 @@ export const BaseTooltip = ({
174
151
  targetStyle,
175
152
  width,
176
153
  position = 'top',
154
+ alignment = 'middle',
177
155
  dataAttributes,
178
156
  delay = true,
179
157
  centerContent,
@@ -183,7 +161,12 @@ export const BaseTooltip = ({
183
161
  hasPointerInteractionOnly = false,
184
162
  trackingEvent,
185
163
  }: BaseTooltipProps): JSX.Element => {
186
- const {texts, t} = useTheme();
164
+ const {texts, t, borderRadii} = useTheme();
165
+ const arrowOffsetFromBorder = parseFloat(borderRadii.popup);
166
+ const minSize = Math.max(
167
+ styles.CONTENT_MIN_WIDTH,
168
+ 2 * (arrowOffsetFromBorder + TOOLTIP_BORDER_SIZE) + ARROW_SIZE
169
+ );
187
170
  const tooltipId = React.useId();
188
171
  const {openTooltipId} = useTooltipState();
189
172
  const {openTooltip, closeTooltip} = useSetTooltipState();
@@ -194,6 +177,7 @@ export const BaseTooltip = ({
194
177
 
195
178
  const targetRef = React.useRef<Element | null>(null);
196
179
  const tooltipRef = React.useRef<HTMLDivElement | null>(null);
180
+ const contentRef = React.useRef<HTMLDivElement | null>(null);
197
181
  const [tooltip, setTooltip] = React.useState<HTMLElement | null>(null);
198
182
  const isTouchable = isTouchableDevice();
199
183
  const tooltipEnterDelay = delay ? TOOLTIP_ENTER_TRANSITION_DELAY_IN_MS : 0;
@@ -208,7 +192,26 @@ export const BaseTooltip = ({
208
192
 
209
193
  const targetRect = useBoundingRect(targetRef, isTooltipOpen);
210
194
  const tooltipRect = useBoundingRect(tooltipRef, isTooltipOpen, true);
195
+ const contentRect = useBoundingRect(contentRef, isTooltipOpen, true);
211
196
  const windowSize = useWindowSize();
197
+ const currentPosition = getFinalPosition(
198
+ targetRect,
199
+ tooltip,
200
+ position,
201
+ windowSize.height,
202
+ windowSize.width,
203
+ contentRect?.height
204
+ );
205
+ const maxHeight = Math.max(
206
+ 0,
207
+ (currentPosition === 'top'
208
+ ? targetRect?.top ?? windowSize.height
209
+ : currentPosition === 'bottom'
210
+ ? windowSize.height - (targetRect?.bottom ?? 0)
211
+ : windowSize.height) -
212
+ (currentPosition === 'top' || currentPosition === 'bottom' ? TOOLTIP_PADDING_FROM_TARGET : 0) -
213
+ 2 * TOOLTIP_BORDER_SIZE
214
+ );
212
215
 
213
216
  const resetTooltipInteractions = React.useCallback(() => {
214
217
  setIsFocused(false);
@@ -227,15 +230,7 @@ export const BaseTooltip = ({
227
230
  return;
228
231
  }
229
232
 
230
- const finalPosition = getFinalPosition(
231
- targetRect,
232
- tooltip,
233
- position,
234
- windowSize.height,
235
- windowSize.width
236
- );
237
-
238
- if (!finalPosition || !targetRect) {
233
+ if (!currentPosition || !targetRect) {
239
234
  setTooltipComputedStyles(undefined);
240
235
  setArrowComputedStyles(undefined);
241
236
  resetTooltipInteractions();
@@ -250,22 +245,29 @@ export const BaseTooltip = ({
250
245
 
251
246
  const maxLeftOffset = windowSize.width - tooltipWidth;
252
247
  const maxTopOffset = windowSize.height - tooltipHeight;
248
+ const alignmentRatio = alignment === 'start' ? 0 : alignment === 'end' ? 1 : 0.5;
249
+ const leftPropInPx = Math.max(
250
+ 0,
251
+ Math.min(maxLeftOffset, left + (right - left - tooltipWidth) * alignmentRatio)
252
+ );
253
+ const topPropInPx = Math.max(
254
+ 0,
255
+ Math.min(maxTopOffset, top + (bottom - top - tooltipHeight) * alignmentRatio)
256
+ );
253
257
 
254
- const arrowOffsetFromViewport = parseInt(getCssVarValue(vars.borderRadii.popup)) ?? 8;
255
-
256
- switch (finalPosition) {
258
+ switch (currentPosition) {
257
259
  case 'top':
258
260
  tooltipStyles = {
259
- left: Math.max(0, Math.min(maxLeftOffset, (left + right - tooltipWidth) / 2)),
261
+ left: leftPropInPx,
260
262
  top: top - tooltipHeight - ARROW_SIZE / 2,
261
263
  padding: `0px 0px ${TOOLTIP_PADDING_FROM_TARGET}px 0px`,
262
264
  };
263
265
 
264
266
  arrowStyles = {
265
267
  left: Math.max(
266
- arrowOffsetFromViewport,
268
+ leftPropInPx + arrowOffsetFromBorder,
267
269
  Math.min(
268
- windowSize.width - arrowOffsetFromViewport - ARROW_SIZE,
270
+ leftPropInPx + tooltipWidth - arrowOffsetFromBorder - ARROW_SIZE,
269
271
  (left + right - ARROW_SIZE) / 2
270
272
  )
271
273
  ),
@@ -276,16 +278,16 @@ export const BaseTooltip = ({
276
278
 
277
279
  case 'bottom':
278
280
  tooltipStyles = {
279
- left: Math.max(0, Math.min(maxLeftOffset, (left + right - tooltipWidth) / 2)),
281
+ left: leftPropInPx,
280
282
  top: bottom - TOOLTIP_OFFSET_FROM_TARGET,
281
283
  padding: `${TOOLTIP_PADDING_FROM_TARGET}px 0px 0px 0px`,
282
284
  };
283
285
 
284
286
  arrowStyles = {
285
287
  left: Math.max(
286
- arrowOffsetFromViewport,
288
+ leftPropInPx + arrowOffsetFromBorder,
287
289
  Math.min(
288
- windowSize.width - arrowOffsetFromViewport - ARROW_SIZE,
290
+ leftPropInPx + tooltipWidth - arrowOffsetFromBorder - ARROW_SIZE,
289
291
  (left + right - ARROW_SIZE) / 2
290
292
  )
291
293
  ),
@@ -298,15 +300,15 @@ export const BaseTooltip = ({
298
300
  case 'left':
299
301
  tooltipStyles = {
300
302
  left: left - tooltipWidth - ARROW_SIZE / 2,
301
- top: Math.max(0, Math.min(maxTopOffset, (top + bottom - tooltipHeight) / 2)),
303
+ top: topPropInPx,
302
304
  padding: `0px ${TOOLTIP_PADDING_FROM_TARGET}px 0px 0px`,
303
305
  };
304
306
 
305
307
  arrowStyles = {
306
308
  top: Math.max(
307
- arrowOffsetFromViewport,
309
+ topPropInPx + arrowOffsetFromBorder,
308
310
  Math.min(
309
- windowSize.height - arrowOffsetFromViewport - ARROW_SIZE,
311
+ topPropInPx + tooltipHeight - arrowOffsetFromBorder - ARROW_SIZE,
310
312
  (top + bottom - ARROW_SIZE) / 2
311
313
  )
312
314
  ),
@@ -318,18 +320,17 @@ export const BaseTooltip = ({
318
320
  break;
319
321
 
320
322
  case 'right':
321
- default:
322
323
  tooltipStyles = {
323
324
  left: right - TOOLTIP_OFFSET_FROM_TARGET,
324
- top: Math.max(0, Math.min(maxTopOffset, (top + bottom - tooltipHeight) / 2)),
325
+ top: topPropInPx,
325
326
  padding: `0px 0px 0px ${TOOLTIP_PADDING_FROM_TARGET}px`,
326
327
  };
327
328
 
328
329
  arrowStyles = {
329
330
  top: Math.max(
330
- arrowOffsetFromViewport,
331
+ topPropInPx + arrowOffsetFromBorder,
331
332
  Math.min(
332
- windowSize.height - arrowOffsetFromViewport - ARROW_SIZE,
333
+ topPropInPx + tooltipHeight - arrowOffsetFromBorder - ARROW_SIZE,
333
334
  (top + bottom - ARROW_SIZE) / 2
334
335
  )
335
336
  ),
@@ -339,6 +340,10 @@ export const BaseTooltip = ({
339
340
  };
340
341
 
341
342
  break;
343
+ default: {
344
+ const exhaustiveCheck: never = currentPosition;
345
+ throw new Error(`Invalid tooltip position: ${exhaustiveCheck}`);
346
+ }
342
347
  }
343
348
 
344
349
  /**
@@ -366,10 +371,12 @@ export const BaseTooltip = ({
366
371
  targetRect,
367
372
  tooltipRect,
368
373
  isTooltipOpen,
369
- position,
374
+ currentPosition,
375
+ alignment,
370
376
  windowSize,
371
377
  tooltipComputedStyles,
372
378
  arrowComputedStyles,
379
+ arrowOffsetFromBorder,
373
380
  isTouchable,
374
381
  tooltipId,
375
382
  resetTooltipInteractions,
@@ -438,17 +445,8 @@ export const BaseTooltip = ({
438
445
  hasControlledValue,
439
446
  ]);
440
447
 
441
- const currentPosition = getFinalPosition(
442
- targetRect,
443
- tooltip,
444
- position,
445
- windowSize.height,
446
- windowSize.width
447
- );
448
-
449
448
  // by default, center content only if tooltip has minimum possible width
450
- const hasCenteredContent =
451
- centerContent !== undefined ? centerContent : tooltipRect?.width === styles.CONTENT_MIN_WIDTH;
449
+ const hasCenteredContent = centerContent !== undefined ? centerContent : tooltipRect?.width === minSize;
452
450
 
453
451
  return (
454
452
  <>
@@ -568,17 +566,23 @@ export const BaseTooltip = ({
568
566
  className={styles.tooltip}
569
567
  style={{
570
568
  width,
569
+ minWidth: minSize,
570
+ minHeight:
571
+ currentPosition === 'left' || currentPosition === 'right'
572
+ ? minSize
573
+ : undefined,
571
574
  ...getBorderStyle(themeVariant),
572
575
  maxWidth: Math.min(TOOLTIP_MAX_WIDTH, windowSize.width),
573
576
  }}
574
577
  >
575
578
  <div
579
+ style={{maxHeight}}
576
580
  className={classNames(styles.contentContainer, {
577
581
  [styles.tooltipCenter]: hasCenteredContent,
578
582
  })}
579
583
  >
580
584
  <ThemeVariant variant="default">
581
- {content}
585
+ <div ref={contentRef}>{content}</div>
582
586
 
583
587
  {onClose && (
584
588
  <div className={styles.closeButtonIcon}>