@telus-uds/components-base 1.24.1 → 1.24.2

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 (50) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/lib/Box/Box.js +3 -1
  3. package/lib/Divider/Divider.js +3 -0
  4. package/lib/FlexGrid/FlexGrid.js +3 -1
  5. package/lib/Link/InlinePressable.js +8 -1
  6. package/lib/Link/LinkBase.js +6 -8
  7. package/lib/StackView/StackView.js +3 -1
  8. package/lib/StackView/StackWrapBox.js +3 -1
  9. package/lib/StackView/StackWrapGap.js +3 -1
  10. package/lib/ThemeProvider/utils/styles.js +1 -3
  11. package/lib/Tooltip/Tooltip.js +85 -158
  12. package/lib/Tooltip/Tooltip.native.js +357 -0
  13. package/lib/Tooltip/index.js +6 -1
  14. package/lib/Tooltip/shared.js +39 -0
  15. package/lib/Typography/Typography.js +3 -1
  16. package/lib/utils/floating-ui/index.js +43 -0
  17. package/lib/utils/floating-ui/index.native.js +43 -0
  18. package/lib-module/Box/Box.js +3 -1
  19. package/lib-module/Divider/Divider.js +3 -0
  20. package/lib-module/FlexGrid/FlexGrid.js +3 -1
  21. package/lib-module/Link/InlinePressable.js +8 -1
  22. package/lib-module/Link/LinkBase.js +6 -8
  23. package/lib-module/StackView/StackView.js +3 -1
  24. package/lib-module/StackView/StackWrapBox.js +3 -1
  25. package/lib-module/StackView/StackWrapGap.js +3 -1
  26. package/lib-module/ThemeProvider/utils/styles.js +1 -3
  27. package/lib-module/Tooltip/Tooltip.js +85 -155
  28. package/lib-module/Tooltip/Tooltip.native.js +326 -0
  29. package/lib-module/Tooltip/index.js +4 -1
  30. package/lib-module/Tooltip/shared.js +27 -0
  31. package/lib-module/Typography/Typography.js +3 -1
  32. package/lib-module/utils/floating-ui/index.js +1 -0
  33. package/lib-module/utils/floating-ui/index.native.js +1 -0
  34. package/package.json +4 -2
  35. package/src/Box/Box.jsx +1 -0
  36. package/src/Divider/Divider.jsx +3 -0
  37. package/src/FlexGrid/FlexGrid.jsx +1 -0
  38. package/src/Link/InlinePressable.jsx +9 -3
  39. package/src/Link/LinkBase.jsx +17 -10
  40. package/src/StackView/StackView.jsx +1 -0
  41. package/src/StackView/StackWrapBox.jsx +1 -0
  42. package/src/StackView/StackWrapGap.jsx +1 -0
  43. package/src/ThemeProvider/utils/styles.js +1 -3
  44. package/src/Tooltip/Tooltip.jsx +79 -156
  45. package/src/Tooltip/Tooltip.native.jsx +283 -0
  46. package/src/Tooltip/index.js +5 -1
  47. package/src/Tooltip/shared.js +27 -0
  48. package/src/Typography/Typography.jsx +1 -0
  49. package/src/utils/floating-ui/index.js +1 -0
  50. package/src/utils/floating-ui/index.native.js +1 -0
@@ -0,0 +1,27 @@
1
+ import PropTypes from 'prop-types';
2
+ import { getTokensPropType, variantProp } from '../utils';
3
+ const propTypes = {
4
+ /**
5
+ * Used to render the control (i.e. tooltip trigger). If a render function is used it will receive the
6
+ * pressable state and tooltip variant as an argument.
7
+ */
8
+ children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
9
+
10
+ /**
11
+ * The message. Can be raw text or text components.
12
+ */
13
+ content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
14
+
15
+ /**
16
+ * Select English or French copy for the accessible label.
17
+ */
18
+ copy: PropTypes.oneOf(['en', 'fr']),
19
+
20
+ /**
21
+ * Use to place the tooltip in a specific location (only if it fits within viewport).
22
+ */
23
+ position: PropTypes.oneOf(['auto', 'above', 'right', 'below', 'left']),
24
+ tokens: getTokensPropType('Tooltip'),
25
+ variant: variantProp.propType
26
+ };
27
+ export default propTypes;
@@ -66,7 +66,9 @@ const Typography = /*#__PURE__*/forwardRef((_ref2, ref) => {
66
66
  dataSet,
67
67
  maxFontSizeMultiplier: getMaxFontMultiplier(themeTokens)
68
68
  };
69
- const containerProps = { ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
69
+ const containerProps = {
70
+ accessibilityRole,
71
+ ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
70
72
  ...selectContainerProps(rest)
71
73
  };
72
74
  return block ? /*#__PURE__*/_jsx(View, {
@@ -0,0 +1 @@
1
+ export { useFloating, arrow, offset, shift, flip, autoPlacement } from '@floating-ui/react-dom';
@@ -0,0 +1 @@
1
+ export { useFloating, arrow, offset, shift, flip, autoPlacement } from '@floating-ui/react-native';
package/package.json CHANGED
@@ -7,6 +7,8 @@
7
7
  "url": "https://github.com/telus/universal-design-system/issues"
8
8
  },
9
9
  "dependencies": {
10
+ "@floating-ui/react-dom": "^1.0.1",
11
+ "@floating-ui/react-native": "^0.8.1",
10
12
  "@gorhom/portal": "^1.0.14",
11
13
  "@telus-uds/system-constants": "^1.2.0",
12
14
  "@telus-uds/system-theme-tokens": "^2.9.0",
@@ -64,11 +66,11 @@
64
66
  "build:main": "babel src -d lib",
65
67
  "build:module": "babel src -d lib-module --env-name module",
66
68
  "build:code": "npm run build:main && npm run build:module",
67
- "build:docs": "babel-node --plugins=@nearform/babel-plugin-react-docgen generate-component-docs.js"
69
+ "build:docs": "babel-node --plugins=@telus-uds/babel-plugin-react-docgen generate-component-docs.js"
68
70
  },
69
71
  "sideEffects": false,
70
72
  "standard-engine": {
71
73
  "skip": true
72
74
  },
73
- "version": "1.24.1"
75
+ "version": "1.24.2"
74
76
  }
package/src/Box/Box.jsx CHANGED
@@ -137,6 +137,7 @@ const Box = forwardRef(
137
137
  ref
138
138
  ) => {
139
139
  const props = {
140
+ accessibilityRole,
140
141
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
141
142
  ...selectProps(rest)
142
143
  }
@@ -72,7 +72,10 @@ const Divider = forwardRef(({ variant, vertical = false, space, tokens, ...rest
72
72
  Platform.OS === 'web'
73
73
  ? // There are aria attributes for dividers on web
74
74
  {
75
+ // Early versions of React Native Web support 'aria-orientation' while
76
+ // later versions only support accessibilityOrientation and map it. Supply both.
75
77
  'aria-orientation': vertical ? 'vertical' : 'horizontal',
78
+ accessibilityOrientation: vertical ? 'vertical' : 'horizontal',
76
79
  accessibilityRole: 'separator'
77
80
  }
78
81
  : // There are no such equivalent attributes for native
@@ -70,6 +70,7 @@ const FlexGrid = forwardRef(
70
70
  }
71
71
 
72
72
  const props = {
73
+ accessibilityRole,
73
74
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
74
75
  ...selectProps(rest)
75
76
  }
@@ -9,16 +9,18 @@ import { Pressable, StyleSheet } from 'react-native'
9
9
  * InlinePressable is an alternative to React Native's Pressable that works better when nested
10
10
  * inline inside Text. It accepts the same props as React Native's Pressable.
11
11
  *
12
+ * On Web it simply passes its props to Pressable and defaults to `inline-flex` instead of `flex`.
13
+ *
12
14
  * @param {PressableProps} PressableProps
13
15
  */
14
16
  // React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
15
17
  // eslint-disable-next-line react/prop-types
16
- const InlinePressable = forwardRef(({ children, style, ...props }, ref) => (
18
+ const InlinePressable = forwardRef(({ children, inlineFlex = true, style, ...props }, ref) => (
17
19
  <Pressable
18
20
  ref={ref}
19
21
  style={(pressState) => [
20
- staticStyles.inline,
21
- typeof style === 'function' ? style(pressState) : style
22
+ typeof style === 'function' ? style(pressState) : style,
23
+ staticStyles[inlineFlex ? 'inlineFlex' : 'inline']
22
24
  ]}
23
25
  {...props}
24
26
  >
@@ -29,7 +31,11 @@ InlinePressable.displayName = 'InlinePressable'
29
31
 
30
32
  const staticStyles = StyleSheet.create({
31
33
  inline: {
34
+ // Stop Pressable defaulting to (block) flex
32
35
  display: 'inline'
36
+ },
37
+ inlineFlex: {
38
+ display: 'inline-flex'
33
39
  }
34
40
  })
35
41
 
@@ -20,10 +20,13 @@ import { IconText, iconComponentPropTypes } from '../Icon'
20
20
 
21
21
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps])
22
22
 
23
- const selectOuterBorderStyles = (
24
- { outerBorderColor, outerBorderWidth, outerBorderGap, borderRadius, outerBorderOutline },
25
- hasIcon
26
- ) =>
23
+ const selectOuterBorderStyles = ({
24
+ outerBorderColor,
25
+ outerBorderWidth,
26
+ outerBorderGap,
27
+ borderRadius,
28
+ outerBorderOutline
29
+ }) =>
27
30
  // A view wrapper with a border on native messes up inline text alignment
28
31
  // so for now make focus styles strictly web-only
29
32
  Platform.OS === 'web'
@@ -35,10 +38,7 @@ const selectOuterBorderStyles = (
35
38
  outerBorderWidth,
36
39
  outerBorderGap,
37
40
  borderRadius
38
- }),
39
- // Stops focus ring stretching horizontally if parent has display: block
40
- // width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
41
- display: hasIcon ? 'inline-flex' : 'inline' // Stop Pressable defaulting to (block) flex
41
+ })
42
42
  }
43
43
  : {}
44
44
 
@@ -144,12 +144,19 @@ const LinkBase = forwardRef(
144
144
  return (
145
145
  <InlinePressable
146
146
  {...selectedProps}
147
+ inlineFlex={hasIcon} // assuming links without icons should be inline (even if they are long)
147
148
  ref={ref}
148
149
  style={(linkState) => {
149
150
  const themeTokens = resolveLinkTokens(linkState)
150
- const outerBorderStyles = selectOuterBorderStyles(themeTokens, hasIcon)
151
+ const outerBorderStyles = selectOuterBorderStyles(themeTokens)
151
152
  const decorationStyles = selectDecorationStyles(themeTokens)
152
- return [outerBorderStyles, blockLeftStyle, decorationStyles, staticStyles.rowContainer]
153
+
154
+ return [
155
+ outerBorderStyles,
156
+ blockLeftStyle,
157
+ decorationStyles,
158
+ hasIcon && staticStyles.rowContainer
159
+ ]
153
160
  }}
154
161
  >
155
162
  {(linkState) => {
@@ -82,6 +82,7 @@ const StackView = forwardRef(
82
82
  const viewport = useViewport()
83
83
  const direction = useResponsiveProp(directionProp, 'column')
84
84
  const selectedProps = selectProps({
85
+ accessibilityRole,
85
86
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
86
87
  ...rest
87
88
  })
@@ -67,6 +67,7 @@ const StackWrapBox = forwardRef(
67
67
  const themeTokens = useThemeTokens('StackView', tokens, variant, { viewport })
68
68
  const flexStyles = selectFlexStyles(themeTokens)
69
69
  const selectedProps = selectProps({
70
+ accessibilityRole,
70
71
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
71
72
  ...rest
72
73
  })
@@ -46,6 +46,7 @@ const StackWrapGap = forwardRef(
46
46
  const themeTokens = useThemeTokens('StackView', tokens, variant, { viewport })
47
47
  const flexStyles = selectFlexStyles(themeTokens)
48
48
  const selectedProps = selectProps({
49
+ accessibilityRole,
49
50
  ...getA11yPropsFromHtmlTag(tag, accessibilityRole),
50
51
  ...rest
51
52
  })
@@ -45,9 +45,7 @@ export function applyTextStyles({
45
45
  // Don't set undefined font families. May need some validation here that the font is available.
46
46
  // Android doesn't recognise font weights natively so apply custom font weights via `fontFamily`.
47
47
  styles.fontFamily = `${fontName}${fontWeight}${fontStyle}`
48
- }
49
-
50
- if (fontWeight) {
48
+ } else if (fontWeight) {
51
49
  // If using system default font, apply the font weight directly.
52
50
  // Font weight support in Android is limited to 'bold' or anything else === 'normal'.
53
51
  styles.fontWeight = Platform.OS === 'android' && Number(fontWeight) > 400 ? 'bold' : fontWeight
@@ -1,18 +1,10 @@
1
1
  import React, { forwardRef, useEffect, useRef, useState } from 'react'
2
- import { Dimensions, Platform, Pressable, StyleSheet, Text, View } from 'react-native'
2
+ import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
3
+ import propTypes from './shared'
4
+ import { useFloating, arrow, offset, shift, flip, autoPlacement } from '../utils/floating-ui'
3
5
 
4
- import PropTypes from 'prop-types'
5
6
  import { applyShadowToken, applyTextStyles, useThemeTokens } from '../ThemeProvider'
6
- import {
7
- a11yProps,
8
- getTokensPropType,
9
- selectSystemProps,
10
- selectTokens,
11
- variantProp,
12
- viewProps
13
- } from '../utils'
14
- import Backdrop from './Backdrop'
15
- import getTooltipPosition from './getTooltipPosition'
7
+ import { a11yProps, selectSystemProps, selectTokens, viewProps } from '../utils'
16
8
  import TooltipButton from '../TooltipButton'
17
9
  import useCopy from '../utils/useCopy'
18
10
  import dictionary from './dictionary'
@@ -38,53 +30,34 @@ const selectTooltipShadowStyles = ({ shadow, borderRadius }) => ({
38
30
  borderRadius,
39
31
  ...applyShadowToken(shadow)
40
32
  })
41
- const selectTooltipPositionStyles = ({ top, left, width }) => {
42
- return { top, left, width }
33
+
34
+ const selectMobileTooltipPositionStyles = ({ top, left, position }) => {
35
+ return { top, left, position }
43
36
  }
44
- const selectArrowStyles = (
37
+
38
+ const selectMobileArrowStyles = (
45
39
  { backgroundColor, arrowWidth, arrowBorderRadius, shadow },
46
- { position, width: tooltipWidth, height: tooltipHeight }
40
+ { placement, x: arrowX, y: arrowY }
47
41
  ) => {
48
- // the arrow width is actually a diagonal of the rectangle that we'll use as a tip
49
- const rectangleSide = Math.sqrt((arrowWidth * arrowWidth) / 2)
50
-
51
- // position the arrow at the side and center of the tooltip - this happens before rotation
52
- // so we use the rectangle size as basis
53
- const verticalOffset = (-1 * rectangleSide) / 2
54
- const horizontalOffset = rectangleSide / 2
55
-
56
- // percentage-based absolute positioning doesn't act well on native, so we have to
57
- // calculate the pixel values
58
- const directionalStyles = {
59
- above: {
60
- bottom: verticalOffset,
61
- left: tooltipWidth / 2 - horizontalOffset,
62
- transform: [{ rotateZ: '45deg' }]
63
- },
64
- below: {
65
- top: verticalOffset,
66
- left: tooltipWidth / 2 - horizontalOffset,
67
- transform: [{ rotateZ: '-135deg' }]
68
- },
69
- left: {
70
- right: verticalOffset,
71
- top: tooltipHeight / 2 - horizontalOffset,
72
- transform: [{ rotateZ: '-45deg' }]
73
- },
74
- right: {
75
- left: verticalOffset,
76
- top: tooltipHeight / 2 - horizontalOffset,
77
- transform: [{ rotateZ: '135deg' }]
78
- }
79
- }
42
+ const staticSide = {
43
+ top: 'bottom',
44
+ right: 'left',
45
+ bottom: 'top',
46
+ left: 'right'
47
+ }[placement.split('-')[0]]
80
48
 
81
49
  return {
82
50
  backgroundColor,
83
- width: rectangleSide,
84
- height: rectangleSide,
51
+ width: arrowWidth,
52
+ height: arrowWidth,
85
53
  borderBottomRightRadius: arrowBorderRadius, // this corner will be the arrow tip after rotation
54
+ transform: [{ rotateZ: '45deg' }],
86
55
  ...applyShadowToken(shadow),
87
- ...directionalStyles[position]
56
+ left: arrowX != null && arrowX,
57
+ top: arrowY != null && arrowY,
58
+ right: '',
59
+ bottom: '',
60
+ [staticSide]: '-4px'
88
61
  }
89
62
  }
90
63
 
@@ -111,26 +84,37 @@ const defaultControl = (pressableState, variant) => (
111
84
  const Tooltip = forwardRef(
112
85
  ({ children, content, position = 'auto', copy = 'en', tokens, variant, ...rest }, ref) => {
113
86
  const [isOpen, setIsOpen] = useState(false)
87
+ const arrowRef = useRef()
114
88
 
115
- const controlRef = useRef()
116
- const [controlLayout, setControlLayout] = useState(null)
117
89
  const [tooltipDimensions, setTooltipDimensions] = useState(null)
118
- const [windowDimensions, setWindowDimensions] = useState(Dimensions.get('window'))
119
- const [tooltipPosition, setTooltipPosition] = useState(null)
120
90
 
121
- const getCopy = useCopy({ dictionary, copy })
122
- const themeTokens = useThemeTokens('Tooltip', tokens, variant)
123
-
124
- const { arrowWidth, arrowOffset } = themeTokens
125
-
126
- useEffect(() => {
127
- const subscription = Dimensions.addEventListener('change', ({ window }) => {
128
- setWindowDimensions(window)
129
- })
91
+ const positions = {
92
+ auto: undefined, // Auto needs to specifically bet set to undefined
93
+ above: 'top',
94
+ right: 'right',
95
+ below: 'bottom',
96
+ left: 'left'
97
+ }
130
98
 
131
- return () => subscription?.remove()
99
+ // "AutoPlacement" can't be used with "flip"
100
+ const additionalMiddleware = position !== 'auto' ? autoPlacement : flip
101
+
102
+ const {
103
+ x,
104
+ y,
105
+ reference,
106
+ floating,
107
+ strategy,
108
+ placement,
109
+ middlewareData: { arrow: arrowData = {} }
110
+ } = useFloating({
111
+ placement: positions[position],
112
+ middleware: [shift(), additionalMiddleware(), offset(15), arrow({ element: arrowRef })]
132
113
  })
133
114
 
115
+ const getCopy = useCopy({ dictionary, copy })
116
+ const themeTokens = useThemeTokens('Tooltip', tokens, variant)
117
+
134
118
  const toggleIsOpen = () => setIsOpen(!isOpen)
135
119
  const close = () => setIsOpen(false)
136
120
 
@@ -161,56 +145,11 @@ const Tooltip = forwardRef(
161
145
  }
162
146
 
163
147
  useEffect(() => {
164
- if (isOpen) {
165
- controlRef.current.measureInWindow((x, y, width, height) => {
166
- setControlLayout({ x, y, width, height })
167
- })
168
- } else {
169
- setControlLayout(null)
148
+ if (!isOpen) {
170
149
  setTooltipDimensions(null)
171
- setTooltipPosition(null)
172
150
  }
173
151
  }, [isOpen])
174
152
 
175
- useEffect(() => {
176
- setIsOpen(false)
177
- }, [windowDimensions])
178
-
179
- useEffect(() => {
180
- if (
181
- (tooltipPosition !== null && !tooltipPosition?.isNormalized) ||
182
- !isOpen ||
183
- controlLayout === null ||
184
- tooltipDimensions == null
185
- ) {
186
- return
187
- }
188
-
189
- const updatedPosition = getTooltipPosition(position, {
190
- controlLayout,
191
- tooltipDimensions,
192
- windowDimensions,
193
- arrowWidth,
194
- arrowOffset
195
- })
196
-
197
- // avoid ending up in an infinite normalization loop
198
- if (tooltipPosition?.isNormalized && updatedPosition.isNormalized) {
199
- return
200
- }
201
-
202
- setTooltipPosition(updatedPosition)
203
- }, [
204
- isOpen,
205
- position,
206
- tooltipDimensions,
207
- controlLayout,
208
- windowDimensions,
209
- arrowWidth,
210
- arrowOffset,
211
- tooltipPosition
212
- ])
213
-
214
153
  const control = children !== undefined ? children : defaultControl
215
154
  const pressableStyles =
216
155
  control === defaultControl ? Platform.select({ web: { outline: 'none' } }) : undefined
@@ -218,10 +157,10 @@ const Tooltip = forwardRef(
218
157
  control === defaultControl ? { top: 10, bottom: 10, left: 10, right: 10 } : undefined
219
158
 
220
159
  return (
221
- <View style={staticStyles.container} {...selectProps(rest)}>
160
+ <View style={staticStyles.container} {...selectProps(rest)} ref={ref}>
222
161
  <Pressable
223
162
  onPress={toggleIsOpen}
224
- ref={controlRef}
163
+ ref={reference}
225
164
  onBlur={close}
226
165
  style={pressableStyles}
227
166
  hitSlop={pressableHitSlop}
@@ -233,30 +172,34 @@ const Tooltip = forwardRef(
233
172
  : control}
234
173
  </Pressable>
235
174
  {isOpen && (
236
- <Backdrop onPress={close}>
175
+ <View
176
+ ref={floating}
177
+ style={[
178
+ selectTooltipShadowStyles(themeTokens),
179
+ staticStyles.tooltip, // applied separately so that it doesn't cover the arrow
180
+ selectMobileTooltipPositionStyles({
181
+ position: strategy,
182
+ top: y ?? 0,
183
+ left: x ?? 0
184
+ })
185
+ ]}
186
+ onLayout={onTooltipLayout}
187
+ accessibilityRole="alert"
188
+ >
237
189
  <View
238
- ref={ref}
239
190
  style={[
240
- staticStyles.tooltip,
241
- selectTooltipShadowStyles(themeTokens), // applied separately so that it doesn't cover the arrow
242
- tooltipPosition && selectTooltipPositionStyles(tooltipPosition),
243
- (tooltipPosition === null || tooltipPosition?.isNormalized) &&
244
- staticStyles.tooltipHidden // visually hide the tooltip until we have a final measurement
191
+ staticStyles.arrow,
192
+ selectMobileArrowStyles(themeTokens, {
193
+ ...arrowData,
194
+ placement
195
+ })
245
196
  ]}
246
- onLayout={onTooltipLayout}
247
- accessibilityRole="alert"
248
- >
249
- <View
250
- style={[
251
- staticStyles.arrow,
252
- tooltipPosition && selectArrowStyles(themeTokens, tooltipPosition)
253
- ]}
254
- />
255
- <View style={selectTooltipStyles(themeTokens)}>
256
- <Text style={selectTextStyles(themeTokens)}>{content}</Text>
257
- </View>
197
+ ref={arrowRef}
198
+ />
199
+ <View style={selectTooltipStyles(themeTokens)}>
200
+ <Text style={selectTextStyles(themeTokens)}>{content}</Text>
258
201
  </View>
259
- </Backdrop>
202
+ </View>
260
203
  )}
261
204
  </View>
262
205
  )
@@ -266,32 +209,15 @@ Tooltip.displayName = 'Tooltip'
266
209
 
267
210
  Tooltip.propTypes = {
268
211
  ...selectedSystemPropTypes,
269
- /**
270
- * Used to render the control (i.e. tooltip trigger). If a render function is used it will receive the
271
- * pressable state and tooltip variant as an argument.
272
- */
273
- children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
274
- /**
275
- * The message. Can be raw text or text components.
276
- */
277
- content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
278
- /**
279
- * Select English or French copy for the accessible label.
280
- */
281
- copy: PropTypes.oneOf(['en', 'fr']),
282
- /**
283
- * Use to place the tooltip in a specific location (only if it fits within viewport).
284
- */
285
- position: PropTypes.oneOf(['auto', 'above', 'right', 'below', 'left']),
286
- tokens: getTokensPropType('Tooltip'),
287
- variant: variantProp.propType
212
+ ...propTypes
288
213
  }
289
214
 
290
215
  export default Tooltip
291
216
 
292
217
  const staticStyles = StyleSheet.create({
293
218
  container: {
294
- alignItems: 'flex-start'
219
+ alignItems: 'flex-start',
220
+ position: 'absolute'
295
221
  },
296
222
  tooltip: {
297
223
  position: 'absolute',
@@ -299,9 +225,6 @@ const staticStyles = StyleSheet.create({
299
225
  top: 0,
300
226
  left: 0
301
227
  },
302
- tooltipHidden: {
303
- opacity: 0
304
- },
305
228
  arrow: {
306
229
  position: 'absolute'
307
230
  }