@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.
- package/CHANGELOG.md +13 -2
- package/lib/Box/Box.js +3 -1
- package/lib/Divider/Divider.js +3 -0
- package/lib/FlexGrid/FlexGrid.js +3 -1
- package/lib/Link/InlinePressable.js +8 -1
- package/lib/Link/LinkBase.js +6 -8
- package/lib/StackView/StackView.js +3 -1
- package/lib/StackView/StackWrapBox.js +3 -1
- package/lib/StackView/StackWrapGap.js +3 -1
- package/lib/ThemeProvider/utils/styles.js +1 -3
- package/lib/Tooltip/Tooltip.js +85 -158
- package/lib/Tooltip/Tooltip.native.js +357 -0
- package/lib/Tooltip/index.js +6 -1
- package/lib/Tooltip/shared.js +39 -0
- package/lib/Typography/Typography.js +3 -1
- package/lib/utils/floating-ui/index.js +43 -0
- package/lib/utils/floating-ui/index.native.js +43 -0
- package/lib-module/Box/Box.js +3 -1
- package/lib-module/Divider/Divider.js +3 -0
- package/lib-module/FlexGrid/FlexGrid.js +3 -1
- package/lib-module/Link/InlinePressable.js +8 -1
- package/lib-module/Link/LinkBase.js +6 -8
- package/lib-module/StackView/StackView.js +3 -1
- package/lib-module/StackView/StackWrapBox.js +3 -1
- package/lib-module/StackView/StackWrapGap.js +3 -1
- package/lib-module/ThemeProvider/utils/styles.js +1 -3
- package/lib-module/Tooltip/Tooltip.js +85 -155
- package/lib-module/Tooltip/Tooltip.native.js +326 -0
- package/lib-module/Tooltip/index.js +4 -1
- package/lib-module/Tooltip/shared.js +27 -0
- package/lib-module/Typography/Typography.js +3 -1
- package/lib-module/utils/floating-ui/index.js +1 -0
- package/lib-module/utils/floating-ui/index.native.js +1 -0
- package/package.json +4 -2
- package/src/Box/Box.jsx +1 -0
- package/src/Divider/Divider.jsx +3 -0
- package/src/FlexGrid/FlexGrid.jsx +1 -0
- package/src/Link/InlinePressable.jsx +9 -3
- package/src/Link/LinkBase.jsx +17 -10
- package/src/StackView/StackView.jsx +1 -0
- package/src/StackView/StackWrapBox.jsx +1 -0
- package/src/StackView/StackWrapGap.jsx +1 -0
- package/src/ThemeProvider/utils/styles.js +1 -3
- package/src/Tooltip/Tooltip.jsx +79 -156
- package/src/Tooltip/Tooltip.native.jsx +283 -0
- package/src/Tooltip/index.js +5 -1
- package/src/Tooltip/shared.js +27 -0
- package/src/Typography/Typography.jsx +1 -0
- package/src/utils/floating-ui/index.js +1 -0
- 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 = {
|
|
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=@
|
|
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.
|
|
75
|
+
"version": "1.24.2"
|
|
74
76
|
}
|
package/src/Box/Box.jsx
CHANGED
package/src/Divider/Divider.jsx
CHANGED
|
@@ -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
|
|
@@ -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
|
-
|
|
21
|
-
|
|
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
|
|
package/src/Link/LinkBase.jsx
CHANGED
|
@@ -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
|
-
|
|
25
|
-
|
|
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
|
|
151
|
+
const outerBorderStyles = selectOuterBorderStyles(themeTokens)
|
|
151
152
|
const decorationStyles = selectDecorationStyles(themeTokens)
|
|
152
|
-
|
|
153
|
+
|
|
154
|
+
return [
|
|
155
|
+
outerBorderStyles,
|
|
156
|
+
blockLeftStyle,
|
|
157
|
+
decorationStyles,
|
|
158
|
+
hasIcon && staticStyles.rowContainer
|
|
159
|
+
]
|
|
153
160
|
}}
|
|
154
161
|
>
|
|
155
162
|
{(linkState) => {
|
|
@@ -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
|
package/src/Tooltip/Tooltip.jsx
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import React, { forwardRef, useEffect, useRef, useState } from 'react'
|
|
2
|
-
import {
|
|
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
|
-
|
|
42
|
-
|
|
33
|
+
|
|
34
|
+
const selectMobileTooltipPositionStyles = ({ top, left, position }) => {
|
|
35
|
+
return { top, left, position }
|
|
43
36
|
}
|
|
44
|
-
|
|
37
|
+
|
|
38
|
+
const selectMobileArrowStyles = (
|
|
45
39
|
{ backgroundColor, arrowWidth, arrowBorderRadius, shadow },
|
|
46
|
-
{
|
|
40
|
+
{ placement, x: arrowX, y: arrowY }
|
|
47
41
|
) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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:
|
|
84
|
-
height:
|
|
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
|
-
|
|
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
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
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={
|
|
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
|
-
<
|
|
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.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
191
|
+
staticStyles.arrow,
|
|
192
|
+
selectMobileArrowStyles(themeTokens, {
|
|
193
|
+
...arrowData,
|
|
194
|
+
placement
|
|
195
|
+
})
|
|
245
196
|
]}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
>
|
|
249
|
-
<
|
|
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
|
-
</
|
|
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
|
}
|