@telus-uds/components-base 1.12.0 → 1.14.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.
- package/CHANGELOG.md +41 -2
- package/component-docs.json +933 -55
- package/lib/BaseProvider/index.js +7 -2
- package/lib/Button/ButtonBase.js +52 -19
- package/lib/Button/ButtonGroup.js +7 -0
- package/lib/Button/propTypes.js +18 -0
- package/lib/Carousel/Carousel.js +83 -58
- package/lib/Carousel/CarouselContext.js +22 -8
- package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +73 -0
- package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
- package/lib/Carousel/CarouselStepTracker/index.js +13 -0
- package/lib/Carousel/CarouselTabs/CarouselTabs.js +70 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +95 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanelItem.js +148 -0
- package/lib/Carousel/CarouselTabs/index.js +13 -0
- package/lib/Carousel/CarouselThumbnail.js +99 -0
- package/lib/Carousel/CarouselThumbnailNavigation.js +87 -0
- package/lib/Carousel/dictionary.js +4 -2
- package/lib/Carousel/index.js +10 -1
- package/lib/Checkbox/Checkbox.js +7 -3
- package/lib/Checkbox/CheckboxGroup.js +8 -1
- package/lib/Feedback/Feedback.js +18 -10
- package/lib/Icon/IconText.js +6 -1
- package/lib/InputLabel/InputLabel.js +11 -5
- package/lib/Link/InlinePressable.js +1 -8
- package/lib/Link/LinkBase.js +13 -10
- package/lib/List/ListItem.js +8 -4
- package/lib/Notification/Notification.js +44 -24
- package/lib/Pagination/Pagination.js +7 -3
- package/lib/Radio/RadioGroup.js +8 -0
- package/lib/RadioCard/RadioCard.js +6 -1
- package/lib/RadioCard/RadioCardGroup.js +7 -0
- package/lib/Select/Select.js +7 -3
- package/lib/SkipLink/SkipLink.js +216 -0
- package/lib/SkipLink/index.js +13 -0
- package/lib/StepTracker/Step.js +8 -4
- package/lib/StepTracker/StepTracker.js +7 -3
- package/lib/Tabs/TabsItem.js +4 -0
- package/lib/TextInput/TextInputBase.js +7 -3
- package/lib/ThemeProvider/ThemeProvider.js +25 -3
- package/lib/ThemeProvider/utils/styles.js +8 -1
- package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib/Typography/Typography.js +6 -2
- package/lib/index.js +9 -0
- package/lib-module/BaseProvider/index.js +7 -2
- package/lib-module/Button/ButtonBase.js +41 -9
- package/lib-module/Button/ButtonGroup.js +7 -0
- package/lib-module/Button/propTypes.js +17 -0
- package/lib-module/Carousel/Carousel.js +80 -57
- package/lib-module/Carousel/CarouselContext.js +21 -8
- package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +51 -0
- package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
- package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabs.js +50 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +76 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanelItem.js +126 -0
- package/lib-module/Carousel/CarouselTabs/index.js +2 -0
- package/lib-module/Carousel/CarouselThumbnail.js +85 -0
- package/lib-module/Carousel/CarouselThumbnailNavigation.js +66 -0
- package/lib-module/Carousel/dictionary.js +4 -2
- package/lib-module/Carousel/index.js +2 -1
- package/lib-module/Checkbox/Checkbox.js +8 -4
- package/lib-module/Checkbox/CheckboxGroup.js +8 -1
- package/lib-module/Feedback/Feedback.js +19 -11
- package/lib-module/Icon/IconText.js +6 -1
- package/lib-module/InputLabel/InputLabel.js +12 -6
- package/lib-module/Link/InlinePressable.js +1 -8
- package/lib-module/Link/LinkBase.js +14 -11
- package/lib-module/List/ListItem.js +9 -5
- package/lib-module/Notification/Notification.js +46 -26
- package/lib-module/Pagination/Pagination.js +8 -4
- package/lib-module/Radio/RadioGroup.js +8 -0
- package/lib-module/RadioCard/RadioCard.js +7 -2
- package/lib-module/RadioCard/RadioCardGroup.js +7 -0
- package/lib-module/Select/Select.js +8 -4
- package/lib-module/SkipLink/SkipLink.js +188 -0
- package/lib-module/SkipLink/index.js +2 -0
- package/lib-module/StepTracker/Step.js +9 -5
- package/lib-module/StepTracker/StepTracker.js +8 -4
- package/lib-module/Tabs/TabsItem.js +5 -1
- package/lib-module/TextInput/TextInputBase.js +8 -4
- package/lib-module/ThemeProvider/ThemeProvider.js +24 -3
- package/lib-module/ThemeProvider/utils/styles.js +8 -1
- package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib-module/Typography/Typography.js +7 -3
- package/lib-module/index.js +1 -0
- package/package.json +46 -47
- package/src/BaseProvider/index.jsx +6 -3
- package/src/Button/ButtonBase.jsx +36 -12
- package/src/Button/ButtonGroup.jsx +6 -0
- package/src/Button/propTypes.js +14 -0
- package/src/Carousel/Carousel.jsx +91 -64
- package/src/Carousel/CarouselContext.jsx +29 -5
- package/src/Carousel/CarouselFirstFocus/CarouselFirstFocus.jsx +49 -0
- package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
- package/src/Carousel/CarouselStepTracker/index.js +3 -0
- package/src/Carousel/CarouselTabs/CarouselTabs.jsx +37 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +69 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanelItem.jsx +119 -0
- package/src/Carousel/CarouselTabs/index.js +3 -0
- package/src/Carousel/CarouselThumbnail.jsx +77 -0
- package/src/Carousel/CarouselThumbnailNavigation.jsx +53 -0
- package/src/Carousel/dictionary.js +4 -2
- package/src/Carousel/index.js +1 -0
- package/src/Checkbox/Checkbox.jsx +14 -11
- package/src/Checkbox/CheckboxGroup.jsx +8 -1
- package/src/Feedback/Feedback.jsx +14 -7
- package/src/Icon/IconText.jsx +3 -1
- package/src/InputLabel/InputLabel.jsx +13 -12
- package/src/Link/InlinePressable.jsx +2 -8
- package/src/Link/LinkBase.jsx +18 -21
- package/src/List/ListItem.jsx +10 -5
- package/src/Notification/Notification.jsx +40 -23
- package/src/Pagination/Pagination.jsx +6 -4
- package/src/Radio/RadioGroup.jsx +7 -0
- package/src/RadioCard/RadioCard.jsx +3 -2
- package/src/RadioCard/RadioCardGroup.jsx +6 -0
- package/src/Select/Select.jsx +12 -3
- package/src/SkipLink/SkipLink.jsx +179 -0
- package/src/SkipLink/index.js +3 -0
- package/src/StepTracker/Step.jsx +12 -4
- package/src/StepTracker/StepTracker.jsx +11 -10
- package/src/Tabs/TabsItem.jsx +3 -2
- package/src/TextInput/TextInputBase.jsx +11 -3
- package/src/ThemeProvider/ThemeProvider.jsx +22 -3
- package/src/ThemeProvider/utils/styles.js +9 -1
- package/src/ThemeProvider/utils/theme-tokens.js +1 -1
- package/src/ToggleSwitch/ToggleSwitchGroup.jsx +6 -0
- package/src/Typography/Typography.jsx +11 -12
- package/src/index.js +1 -0
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
viewProps,
|
|
12
12
|
withLinkRouter
|
|
13
13
|
} from '../utils'
|
|
14
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
|
|
14
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
|
|
15
15
|
import { useViewport } from '../ViewportProvider'
|
|
16
16
|
import Box from '../Box'
|
|
17
17
|
|
|
@@ -21,13 +21,14 @@ import SideButton from './SideButton'
|
|
|
21
21
|
|
|
22
22
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
23
23
|
|
|
24
|
-
const selectTextStyles = ({ color, fontName, fontSize, fontWeight, lineHeight }) =>
|
|
24
|
+
const selectTextStyles = ({ color, fontName, fontSize, fontWeight, lineHeight }, themeOptions) =>
|
|
25
25
|
applyTextStyles({
|
|
26
26
|
color,
|
|
27
27
|
fontName,
|
|
28
28
|
fontSize,
|
|
29
29
|
fontWeight,
|
|
30
|
-
lineHeight
|
|
30
|
+
lineHeight,
|
|
31
|
+
themeOptions
|
|
31
32
|
})
|
|
32
33
|
|
|
33
34
|
const Pagination = forwardRef(
|
|
@@ -49,6 +50,7 @@ const Pagination = forwardRef(
|
|
|
49
50
|
const { truncateAbove, gap, ...themeTokens } = useThemeTokens('Pagination', tokens, variant, {
|
|
50
51
|
viewport
|
|
51
52
|
})
|
|
53
|
+
const { themeOptions } = useTheme()
|
|
52
54
|
|
|
53
55
|
const items = React.Children.toArray(children)
|
|
54
56
|
|
|
@@ -66,7 +68,7 @@ const Pagination = forwardRef(
|
|
|
66
68
|
truncateAbove
|
|
67
69
|
})
|
|
68
70
|
|
|
69
|
-
const ellipsisTextStyles = selectTextStyles(themeTokens)
|
|
71
|
+
const ellipsisTextStyles = selectTextStyles(themeTokens, themeOptions)
|
|
70
72
|
|
|
71
73
|
if (items.length === 0) {
|
|
72
74
|
return null
|
package/src/Radio/RadioGroup.jsx
CHANGED
|
@@ -84,6 +84,7 @@ const RadioGroup = forwardRef(
|
|
|
84
84
|
legend,
|
|
85
85
|
tooltip,
|
|
86
86
|
hint,
|
|
87
|
+
hintPosition = 'inline',
|
|
87
88
|
validation,
|
|
88
89
|
feedback,
|
|
89
90
|
initialCheckedId,
|
|
@@ -125,6 +126,7 @@ const RadioGroup = forwardRef(
|
|
|
125
126
|
|
|
126
127
|
return (
|
|
127
128
|
<Radio
|
|
129
|
+
error={validation === 'error'}
|
|
128
130
|
ref={itemRef}
|
|
129
131
|
key={radioId}
|
|
130
132
|
id={radioId}
|
|
@@ -149,6 +151,7 @@ const RadioGroup = forwardRef(
|
|
|
149
151
|
legend={legend}
|
|
150
152
|
tooltip={tooltip}
|
|
151
153
|
hint={hint}
|
|
154
|
+
hintPosition={hintPosition}
|
|
152
155
|
space={fieldSpace}
|
|
153
156
|
feedback={feedback}
|
|
154
157
|
inactive={inactive}
|
|
@@ -201,6 +204,10 @@ RadioGroup.propTypes = {
|
|
|
201
204
|
* Optional additional text giving more detail to help a user make a choice.
|
|
202
205
|
*/
|
|
203
206
|
hint: PropTypes.string,
|
|
207
|
+
/**
|
|
208
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
209
|
+
*/
|
|
210
|
+
hintPosition: PropTypes.oneOf(['inline', 'below']),
|
|
204
211
|
/**
|
|
205
212
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
206
213
|
*/
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { StyleSheet, Text, View } from 'react-native'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokensCallback } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
focusHandlerProps,
|
|
@@ -96,6 +96,7 @@ const RadioCard = forwardRef(
|
|
|
96
96
|
|
|
97
97
|
const getTokens = useThemeTokensCallback('RadioCard', tokens, variant)
|
|
98
98
|
const getCardTokens = (cardState) => selectPressableCardTokens(getTokens(cardState))
|
|
99
|
+
const { themeOptions } = useTheme()
|
|
99
100
|
|
|
100
101
|
return (
|
|
101
102
|
<PressableCardBase
|
|
@@ -112,7 +113,7 @@ const RadioCard = forwardRef(
|
|
|
112
113
|
const { radioSpace, contentSpace, ...themeTokens } = getTokens(cardState)
|
|
113
114
|
const radioTokens = selectRadioButtonTokens(themeTokens, 'radio')
|
|
114
115
|
const titleTokens = selectTokens('Typography', themeTokens)
|
|
115
|
-
const textStyle = applyTextStyles(titleTokens)
|
|
116
|
+
const textStyle = applyTextStyles({ ...titleTokens, themeOptions })
|
|
116
117
|
return (
|
|
117
118
|
<StackView direction="row" space={radioSpace}>
|
|
118
119
|
<View style={[staticStyles.alignWithText, { height: textStyle.lineHeight }]}>
|
|
@@ -85,6 +85,7 @@ const RadioCardGroup = forwardRef(
|
|
|
85
85
|
legend,
|
|
86
86
|
tooltip,
|
|
87
87
|
hint,
|
|
88
|
+
hintPosition = 'inline',
|
|
88
89
|
validation,
|
|
89
90
|
feedback,
|
|
90
91
|
initialCheckedId,
|
|
@@ -127,6 +128,7 @@ const RadioCardGroup = forwardRef(
|
|
|
127
128
|
legend={legend}
|
|
128
129
|
tooltip={tooltip}
|
|
129
130
|
hint={hint}
|
|
131
|
+
hintPosition={hintPosition}
|
|
130
132
|
space={fieldSpace}
|
|
131
133
|
feedback={feedback}
|
|
132
134
|
inactive={inactive || readOnly}
|
|
@@ -208,6 +210,10 @@ RadioCardGroup.propTypes = {
|
|
|
208
210
|
* Optional additional text giving more detail to help a user make a choice.
|
|
209
211
|
*/
|
|
210
212
|
hint: PropTypes.string,
|
|
213
|
+
/**
|
|
214
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
215
|
+
*/
|
|
216
|
+
hintPosition: PropTypes.oneOf(['inline', 'below']),
|
|
211
217
|
/**
|
|
212
218
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
213
219
|
*/
|
package/src/Select/Select.jsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { forwardRef, useState } from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { View, Platform, StyleSheet } from 'react-native'
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
|
-
import { applyTextStyles, useThemeTokens, applyOuterBorder } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useThemeTokens, applyOuterBorder, useTheme } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
componentPropType,
|
|
@@ -43,6 +43,7 @@ const selectInputStyles = (
|
|
|
43
43
|
validationIconSize = 0,
|
|
44
44
|
height
|
|
45
45
|
},
|
|
46
|
+
themeOptions,
|
|
46
47
|
inactive
|
|
47
48
|
) => {
|
|
48
49
|
// Subtract border width from padding so overall input width/height doesn't
|
|
@@ -50,7 +51,13 @@ const selectInputStyles = (
|
|
|
50
51
|
const offsetBorder = (value) =>
|
|
51
52
|
typeof value === 'number' ? Math.max(0, value - borderWidth) : value
|
|
52
53
|
|
|
53
|
-
const textStyles = applyTextStyles({
|
|
54
|
+
const textStyles = applyTextStyles({
|
|
55
|
+
fontName,
|
|
56
|
+
fontSize,
|
|
57
|
+
lineHeight,
|
|
58
|
+
fontWeight,
|
|
59
|
+
themeOptions
|
|
60
|
+
})
|
|
54
61
|
|
|
55
62
|
const webStyles = Platform.select({
|
|
56
63
|
web: {
|
|
@@ -205,13 +212,15 @@ const Select = forwardRef(
|
|
|
205
212
|
|
|
206
213
|
const { icon: IconComponent, validationIcon: ValidationIconComponent } = themeTokens
|
|
207
214
|
|
|
215
|
+
const { themeOptions } = useTheme()
|
|
216
|
+
|
|
208
217
|
return (
|
|
209
218
|
<InputSupports {...supportsProps} {...selectedProps}>
|
|
210
219
|
{({ inputId, ...props }) => (
|
|
211
220
|
<View style={selectOuterBorderStyles(themeTokens)}>
|
|
212
221
|
<Picker
|
|
213
222
|
ref={ref}
|
|
214
|
-
style={selectInputStyles(themeTokens, inactive)}
|
|
223
|
+
style={selectInputStyles(themeTokens, themeOptions, inactive)}
|
|
215
224
|
onFocus={handleFocus}
|
|
216
225
|
onBlur={handleBlur}
|
|
217
226
|
onMouseOver={handleMouseOver}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
import { Platform, Pressable, StyleSheet, Text } from 'react-native'
|
|
3
|
+
import PropTypes from 'prop-types'
|
|
4
|
+
|
|
5
|
+
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
6
|
+
import {
|
|
7
|
+
a11yProps,
|
|
8
|
+
clickProps,
|
|
9
|
+
getTokensPropType,
|
|
10
|
+
linkProps,
|
|
11
|
+
resolvePressableTokens,
|
|
12
|
+
selectSystemProps,
|
|
13
|
+
variantProp,
|
|
14
|
+
withLinkRouter
|
|
15
|
+
} from '../utils'
|
|
16
|
+
|
|
17
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps])
|
|
18
|
+
|
|
19
|
+
// ensure explicit selection of tokens
|
|
20
|
+
const selectStyles = ({
|
|
21
|
+
backgroundColor,
|
|
22
|
+
outlineColor,
|
|
23
|
+
outlineOffset,
|
|
24
|
+
outlineStyle,
|
|
25
|
+
outlineWidth,
|
|
26
|
+
paddingHorizontal,
|
|
27
|
+
paddingVertical,
|
|
28
|
+
borderRadius
|
|
29
|
+
}) => ({
|
|
30
|
+
backgroundColor,
|
|
31
|
+
outlineColor,
|
|
32
|
+
outlineOffset,
|
|
33
|
+
outlineStyle,
|
|
34
|
+
outlineWidth,
|
|
35
|
+
paddingHorizontal,
|
|
36
|
+
paddingVertical,
|
|
37
|
+
borderRadius
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const selectTextStyles = ({ color }) => ({
|
|
41
|
+
color
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A generic Skip link component, unstyled by default.
|
|
46
|
+
* A Skip link component help keyboard-only users, screen reader users to skip
|
|
47
|
+
* sections and navigate to the content they want.
|
|
48
|
+
*
|
|
49
|
+
* ## Component API
|
|
50
|
+
*
|
|
51
|
+
* For common uses, pass a `href` that is a # link to a DOM id that can be skipped to (web only).
|
|
52
|
+
*
|
|
53
|
+
* The element with this ID should be focusable, e.g. `<Box nativeID="skip-target" focusable>`.
|
|
54
|
+
*
|
|
55
|
+
* Other custom behaviour may be set by passing an `onPress` function, and routers may be integrated
|
|
56
|
+
* in the same way as other navigation-related components by passing a `LinkRouter`; but a # anchor
|
|
57
|
+
* href on web and/or a `targetRef` for cross-platform applications is the recommended approach.
|
|
58
|
+
*
|
|
59
|
+
* ## Visible styling
|
|
60
|
+
*
|
|
61
|
+
* When focused, the skip link shows as a visible element similar to a simplified ButtonLink using
|
|
62
|
+
* UDS theming. The `tokens` prop may be used to override these styles.
|
|
63
|
+
*
|
|
64
|
+
* To control the background of a skip link, the following tokens can be used:
|
|
65
|
+
*
|
|
66
|
+
* - `backgroundColor`
|
|
67
|
+
* *
|
|
68
|
+
* In order to control the color of the skip link text, the following tokens can be used:
|
|
69
|
+
*
|
|
70
|
+
* - `color`
|
|
71
|
+
*
|
|
72
|
+
* ### Padding
|
|
73
|
+
*
|
|
74
|
+
* The following padding tokens can be used:
|
|
75
|
+
*
|
|
76
|
+
* - `paddingHorizontal`
|
|
77
|
+
* - `paddingVertical`
|
|
78
|
+
*
|
|
79
|
+
* ### Outline
|
|
80
|
+
*
|
|
81
|
+
* The following tokens to control the outline:
|
|
82
|
+
*
|
|
83
|
+
* - `outlineColor`
|
|
84
|
+
* - `outlineOffset`
|
|
85
|
+
* - `outlineStyle`
|
|
86
|
+
* - `outlineWidth`
|
|
87
|
+
*
|
|
88
|
+
* ## Usability and A11y guidelines
|
|
89
|
+
*
|
|
90
|
+
* - The skip link component is visually hidden until a keyboard press activates it.
|
|
91
|
+
* - Usually, you should place the skip link immediately after the opening <body> tag.
|
|
92
|
+
* - This lets users bypass top-level navigation links and jump to the main content on a page.
|
|
93
|
+
* - Also consider using SkipLink before a complex feature containing many focusable elements.
|
|
94
|
+
*
|
|
95
|
+
* ## Accessibility
|
|
96
|
+
*
|
|
97
|
+
* Skip link supports all the common a11y and link props.
|
|
98
|
+
*/
|
|
99
|
+
const SkipLink = forwardRef(({ tokens, variant, href, children, ...rawRest }, ref) => {
|
|
100
|
+
const { onPress, ...rest } = clickProps.toPressProps(rawRest)
|
|
101
|
+
|
|
102
|
+
const getTokens = useThemeTokensCallback('SkipLink', tokens, variant)
|
|
103
|
+
const defaultTokens = getTokens()
|
|
104
|
+
|
|
105
|
+
const resolveLinkTokens = (pressState) => resolvePressableTokens(defaultTokens, pressState)
|
|
106
|
+
|
|
107
|
+
const handlePress = (event) => {
|
|
108
|
+
if (typeof onPress === 'function') onPress(event)
|
|
109
|
+
// TODO - support native apps with something based on refs and/or setAccessibilityFocus
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<Pressable
|
|
114
|
+
ref={ref}
|
|
115
|
+
accessibilityRole="link"
|
|
116
|
+
onPress={handlePress}
|
|
117
|
+
href={href}
|
|
118
|
+
style={({ focused: focus }) => {
|
|
119
|
+
const themeTokens = getTokens({ focus })
|
|
120
|
+
const skipLinkStyle = selectStyles(themeTokens)
|
|
121
|
+
|
|
122
|
+
return [staticStyles.absolute, skipLinkStyle, !focus && staticStyles.hidden]
|
|
123
|
+
}}
|
|
124
|
+
{...selectProps(rest)}
|
|
125
|
+
>
|
|
126
|
+
{(pressState) => {
|
|
127
|
+
const themeTokens = resolveLinkTokens(pressState)
|
|
128
|
+
const textStyles = selectTextStyles(themeTokens)
|
|
129
|
+
|
|
130
|
+
return <Text style={[textStyles, staticStyles.baseline]}>{children}</Text>
|
|
131
|
+
}}
|
|
132
|
+
</Pressable>
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
SkipLink.displayName = 'SkipLink'
|
|
137
|
+
|
|
138
|
+
SkipLink.propTypes = {
|
|
139
|
+
...selectedSystemPropTypes,
|
|
140
|
+
/**
|
|
141
|
+
* The text content shown or read out when the SkipLink is focused, usually a string.
|
|
142
|
+
*/
|
|
143
|
+
children: PropTypes.node,
|
|
144
|
+
/**
|
|
145
|
+
* The target to skip to. Usually an anchor link to a section id (e.g. href="#main-section").
|
|
146
|
+
*/
|
|
147
|
+
href: PropTypes.string,
|
|
148
|
+
tokens: getTokensPropType('SkipLink'),
|
|
149
|
+
variant: variantProp.propType
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const staticStyles = StyleSheet.create({
|
|
153
|
+
baseline: {
|
|
154
|
+
alignSelf: 'baseline'
|
|
155
|
+
},
|
|
156
|
+
absolute: {
|
|
157
|
+
margin: 0,
|
|
158
|
+
position: 'absolute',
|
|
159
|
+
top: 0,
|
|
160
|
+
left: 0
|
|
161
|
+
},
|
|
162
|
+
hidden: {
|
|
163
|
+
overflow: 'hidden',
|
|
164
|
+
...Platform.select({
|
|
165
|
+
web: {
|
|
166
|
+
clip: 'rect(0 0 0 0)',
|
|
167
|
+
clipPath: 'inset(50%)'
|
|
168
|
+
},
|
|
169
|
+
default: {
|
|
170
|
+
// width / height of 0 would make it non-focusable
|
|
171
|
+
height: 1,
|
|
172
|
+
width: 1,
|
|
173
|
+
opacity: 0
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
export default withLinkRouter(SkipLink)
|
package/src/StepTracker/Step.jsx
CHANGED
|
@@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native'
|
|
|
4
4
|
import StackView from '../StackView'
|
|
5
5
|
import Icon from '../Icon'
|
|
6
6
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
|
-
import { applyTextStyles } from '../ThemeProvider'
|
|
7
|
+
import { applyTextStyles, useTheme } from '../ThemeProvider'
|
|
8
8
|
|
|
9
9
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
10
10
|
|
|
@@ -95,6 +95,7 @@ const selectLabelStyles = (
|
|
|
95
95
|
labelFontName,
|
|
96
96
|
labelLineHeight
|
|
97
97
|
},
|
|
98
|
+
themeOptions,
|
|
98
99
|
isCurrent
|
|
99
100
|
) =>
|
|
100
101
|
applyTextStyles({
|
|
@@ -102,7 +103,8 @@ const selectLabelStyles = (
|
|
|
102
103
|
fontSize: labelFontSize,
|
|
103
104
|
lineHeight: labelLineHeight,
|
|
104
105
|
fontWeight: isCurrent ? labelCurrentFontWeight : labelFontWeight,
|
|
105
|
-
fontName: labelFontName
|
|
106
|
+
fontName: labelFontName,
|
|
107
|
+
themeOptions
|
|
106
108
|
})
|
|
107
109
|
const getStepTestID = (isCompleted, isCurrent) => {
|
|
108
110
|
let testID = 'StepTracker-Step'
|
|
@@ -125,6 +127,7 @@ const Step = ({ label, name, status = 0, stepCount = 0, stepIndex = 0, tokens, .
|
|
|
125
127
|
const isCompleted = status > stepIndex
|
|
126
128
|
const isCurrent = status === stepIndex
|
|
127
129
|
const isActive = isCompleted || isCurrent
|
|
130
|
+
const { themeOptions } = useTheme()
|
|
128
131
|
|
|
129
132
|
return (
|
|
130
133
|
<StackView
|
|
@@ -158,7 +161,12 @@ const Step = ({ label, name, status = 0, stepCount = 0, stepIndex = 0, tokens, .
|
|
|
158
161
|
{showStepLabel && (
|
|
159
162
|
<View style={[staticStyles.stepLabelContainer, selectLabelContainerStyles(tokens)]}>
|
|
160
163
|
{showStepName && (
|
|
161
|
-
<Text
|
|
164
|
+
<Text
|
|
165
|
+
style={[
|
|
166
|
+
staticStyles.centeredText,
|
|
167
|
+
selectLabelStyles(tokens, themeOptions, isCurrent)
|
|
168
|
+
]}
|
|
169
|
+
>
|
|
162
170
|
{name}
|
|
163
171
|
</Text>
|
|
164
172
|
)}
|
|
@@ -167,7 +175,7 @@ const Step = ({ label, name, status = 0, stepCount = 0, stepIndex = 0, tokens, .
|
|
|
167
175
|
style={[
|
|
168
176
|
staticStyles.centeredText,
|
|
169
177
|
tokens.labelDirection === 'column' && staticStyles.wrappingLabel,
|
|
170
|
-
selectLabelStyles(tokens, isCurrent)
|
|
178
|
+
selectLabelStyles(tokens, themeOptions, isCurrent)
|
|
171
179
|
]}
|
|
172
180
|
>
|
|
173
181
|
{label}
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { StyleSheet, Text, View } from 'react-native'
|
|
4
4
|
import StackView from '../StackView'
|
|
5
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
|
|
7
7
|
import { useViewport } from '../ViewportProvider'
|
|
8
8
|
import useCopy from '../utils/useCopy'
|
|
@@ -25,19 +25,17 @@ const selectContainerStyles = ({
|
|
|
25
25
|
const selectStepTrackerLabelContainerStyles = ({ labelMarginTop }) => ({
|
|
26
26
|
marginTop: labelMarginTop
|
|
27
27
|
})
|
|
28
|
-
const selectStepTrackerLabelStyles = (
|
|
29
|
-
labelColor,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
labelFontName,
|
|
33
|
-
labelLineHeight
|
|
34
|
-
}) =>
|
|
28
|
+
const selectStepTrackerLabelStyles = (
|
|
29
|
+
{ labelColor, labelFontSize, labelFontWeight, labelFontName, labelLineHeight },
|
|
30
|
+
themeOptions
|
|
31
|
+
) =>
|
|
35
32
|
applyTextStyles({
|
|
36
33
|
color: labelColor,
|
|
37
34
|
fontSize: labelFontSize,
|
|
38
35
|
lineHeight: labelLineHeight,
|
|
39
36
|
fontWeight: labelFontWeight,
|
|
40
|
-
fontName: labelFontName
|
|
37
|
+
fontName: labelFontName,
|
|
38
|
+
themeOptions
|
|
41
39
|
})
|
|
42
40
|
|
|
43
41
|
/**
|
|
@@ -106,6 +104,7 @@ const StepTracker = forwardRef(
|
|
|
106
104
|
: ''
|
|
107
105
|
const getStepLabel = (index) =>
|
|
108
106
|
themeTokens.showStepLabel ? getCopy('stepLabel').replace('%{stepNumber}', index + 1) : ''
|
|
107
|
+
const { themeOptions } = useTheme()
|
|
109
108
|
if (!steps.length) return null
|
|
110
109
|
const selectedProps = selectProps({
|
|
111
110
|
accessibilityLabel: stepTrackerLabel,
|
|
@@ -145,7 +144,9 @@ const StepTracker = forwardRef(
|
|
|
145
144
|
selectStepTrackerLabelContainerStyles(themeTokens)
|
|
146
145
|
]}
|
|
147
146
|
>
|
|
148
|
-
<Text style={selectStepTrackerLabelStyles(themeTokens)}>
|
|
147
|
+
<Text style={selectStepTrackerLabelStyles(themeTokens, themeOptions)}>
|
|
148
|
+
{stepTrackerLabel}
|
|
149
|
+
</Text>
|
|
149
150
|
</View>
|
|
150
151
|
)}
|
|
151
152
|
</StackView>
|
package/src/Tabs/TabsItem.jsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { forwardRef, useEffect } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
|
|
4
4
|
|
|
5
|
-
import { applyTextStyles, useThemeTokensCallback } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokensCallback } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
clickProps,
|
|
@@ -97,7 +97,7 @@ const TabsItem = forwardRef(
|
|
|
97
97
|
) => {
|
|
98
98
|
// Convert onClick etc to onPress etc if used in an integration
|
|
99
99
|
const { onPress, ...rest } = clickProps.toPressProps(rawRest)
|
|
100
|
-
|
|
100
|
+
const { themeOptions } = useTheme()
|
|
101
101
|
const getTokens = useThemeTokensCallback('TabsItem', tokens, variant)
|
|
102
102
|
const resolveTokens = (pressableState) =>
|
|
103
103
|
resolvePressableTokens(getTokens, pressableState, { selected })
|
|
@@ -165,6 +165,7 @@ const TabsItem = forwardRef(
|
|
|
165
165
|
const containerStyles = selectContainerStyles(themeTokens)
|
|
166
166
|
const textStyles = applyTextStyles({
|
|
167
167
|
...selectTokens('Typography', themeTokens),
|
|
168
|
+
themeOptions,
|
|
168
169
|
textAlign
|
|
169
170
|
})
|
|
170
171
|
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef, useEffect, useState } from 'react'
|
|
|
2
2
|
import { Platform, StyleSheet, TextInput as NativeTextInput, View } from 'react-native'
|
|
3
3
|
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
|
-
import { applyTextStyles, useThemeTokens, applyOuterBorder } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokens, applyOuterBorder } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
getTokensPropType,
|
|
@@ -43,6 +43,7 @@ const selectInputStyles = (
|
|
|
43
43
|
width,
|
|
44
44
|
height
|
|
45
45
|
},
|
|
46
|
+
themeOptions,
|
|
46
47
|
inactive
|
|
47
48
|
) => {
|
|
48
49
|
// Subtract border width from padding so overall input width/height doesn't
|
|
@@ -50,7 +51,13 @@ const selectInputStyles = (
|
|
|
50
51
|
const offsetBorder = (value) =>
|
|
51
52
|
typeof value === 'number' ? Math.max(0, value - borderWidth) : value
|
|
52
53
|
|
|
53
|
-
const textStyles = applyTextStyles({
|
|
54
|
+
const textStyles = applyTextStyles({
|
|
55
|
+
fontName,
|
|
56
|
+
fontSize,
|
|
57
|
+
lineHeight,
|
|
58
|
+
fontWeight,
|
|
59
|
+
themeOptions
|
|
60
|
+
})
|
|
54
61
|
|
|
55
62
|
function linesToHeight(lines) {
|
|
56
63
|
const { lineHeight: absoluteLineHeight } = textStyles
|
|
@@ -197,7 +204,8 @@ const TextInputBase = forwardRef(
|
|
|
197
204
|
value: isControlled ? currentValue : undefined
|
|
198
205
|
}
|
|
199
206
|
|
|
200
|
-
const
|
|
207
|
+
const { themeOptions } = useTheme()
|
|
208
|
+
const nativeInputStyle = selectInputStyles({ ...themeTokens, height }, themeOptions, inactive)
|
|
201
209
|
|
|
202
210
|
return (
|
|
203
211
|
<View style={selectOuterBorderStyles(themeTokens)}>
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import React, { createContext, useState } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { validateThemeTokensVersion } from './utils'
|
|
4
|
+
import responsiveProps from '../utils/props/responsiveProps'
|
|
4
5
|
|
|
5
6
|
export const uninitialisedError = new Error('Theme context used outside of ThemeProvider')
|
|
6
7
|
|
|
7
8
|
export const ThemeContext = createContext(uninitialisedError)
|
|
8
9
|
export const ThemeSetterContext = createContext(uninitialisedError)
|
|
9
10
|
|
|
10
|
-
const ThemeProvider = ({
|
|
11
|
+
const ThemeProvider = ({
|
|
12
|
+
children,
|
|
13
|
+
defaultTheme,
|
|
14
|
+
// TODO: switch `forceAbsoluteFontSizing` to be false by default in the next major version
|
|
15
|
+
themeOptions = { forceAbsoluteFontSizing: true }
|
|
16
|
+
}) => {
|
|
11
17
|
const [theme, setTheme] = useState(defaultTheme)
|
|
12
18
|
|
|
13
19
|
// Validate the theme tokens version on every render.
|
|
@@ -17,7 +23,7 @@ const ThemeProvider = ({ children, defaultTheme }) => {
|
|
|
17
23
|
|
|
18
24
|
return (
|
|
19
25
|
<ThemeSetterContext.Provider value={setTheme}>
|
|
20
|
-
<ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
|
26
|
+
<ThemeContext.Provider value={{ ...theme, themeOptions }}>{children}</ThemeContext.Provider>
|
|
21
27
|
</ThemeSetterContext.Provider>
|
|
22
28
|
)
|
|
23
29
|
}
|
|
@@ -28,7 +34,20 @@ ThemeProvider.propTypes = {
|
|
|
28
34
|
metadata: PropTypes.shape({
|
|
29
35
|
themeTokensVersion: PropTypes.string.isRequired
|
|
30
36
|
}).isRequired
|
|
31
|
-
}).isRequired
|
|
37
|
+
}).isRequired,
|
|
38
|
+
/**
|
|
39
|
+
* An object containing options allowing to customize the theming experience:
|
|
40
|
+
*
|
|
41
|
+
* - `forceAbsoluteFontSizing`: available on web only; when set to true, allows
|
|
42
|
+
* using absolute font sizing (in pixels, doesn't scale) instead of the
|
|
43
|
+
* relative sizing (in `rem`, scales depending on the browser settings)
|
|
44
|
+
* - `contentMaxWidth`: allows configuration of the content max width to be used in components
|
|
45
|
+
* such as Footnote and Notification to avoid content to stretch width more then the page's width
|
|
46
|
+
*/
|
|
47
|
+
themeOptions: PropTypes.shape({
|
|
48
|
+
forceAbsoluteFontSizing: PropTypes.bool,
|
|
49
|
+
contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number)
|
|
50
|
+
})
|
|
32
51
|
}
|
|
33
52
|
|
|
34
53
|
export default ThemeProvider
|
|
@@ -15,13 +15,21 @@ export function applyTextStyles({
|
|
|
15
15
|
fontWeight = '400',
|
|
16
16
|
fontName,
|
|
17
17
|
fontStyle = 'normal',
|
|
18
|
+
themeOptions = {
|
|
19
|
+
// TODO: switch `forceAbsoluteFontSizing` to be false by default in the next major version
|
|
20
|
+
forceAbsoluteFontSizing: true
|
|
21
|
+
},
|
|
18
22
|
...rest
|
|
19
23
|
}) {
|
|
20
24
|
const styles = { ...rest }
|
|
25
|
+
const { forceAbsoluteFontSizing } = themeOptions
|
|
21
26
|
|
|
22
27
|
if (fontSize) {
|
|
23
28
|
// If relative font sizes are needed, catch and calculate them here
|
|
24
|
-
styles.fontSize =
|
|
29
|
+
styles.fontSize =
|
|
30
|
+
Platform.OS === 'web' && !forceAbsoluteFontSizing
|
|
31
|
+
? `${fontSize / fontBasePixels}rem`
|
|
32
|
+
: fontSize
|
|
25
33
|
}
|
|
26
34
|
if (typeof lineHeight === 'number') {
|
|
27
35
|
// React Native expects absolute line heights but multipliers are better as design tokens
|
|
@@ -157,7 +157,7 @@ export const validateThemeTokensVersion = (theme) => {
|
|
|
157
157
|
|
|
158
158
|
The UDS base components ${pkg.name} v${pkg.version} are only compatible with UDS themes that are built with @telus-uds/system-theme-tokens version that is semver compatible with ${expectedThemeTokensVersion}. The current theme was built with @telus-uds/system-theme-tokens v${actualThemeTokensVersion}.
|
|
159
159
|
|
|
160
|
-
If you see this error than most likely you have attempted to install ${pkg.name} and a UDS theme manually because you are building a multi-brand application. If you are building a single brand application, consider installing the brand specific design system package such as @telus-uds/ds-allium. For more information, see https://github.com/telus/universal-design-system/blob/main/
|
|
160
|
+
If you see this error than most likely you have attempted to install ${pkg.name} and a UDS theme manually because you are building a multi-brand application. If you are building a single brand application, consider installing the brand specific design system package such as @telus-uds/ds-allium. For more information, see https://github.com/telus/universal-design-system/blob/main/docs/docs/multi-brand-usage.md`
|
|
161
161
|
)
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -40,6 +40,7 @@ const ToggleSwitchGroup = forwardRef(
|
|
|
40
40
|
inactive = false,
|
|
41
41
|
feedback,
|
|
42
42
|
hint,
|
|
43
|
+
hintPosition = 'inline',
|
|
43
44
|
tooltip,
|
|
44
45
|
legend,
|
|
45
46
|
name: inputGroupName,
|
|
@@ -130,6 +131,7 @@ const ToggleSwitchGroup = forwardRef(
|
|
|
130
131
|
legend={legend}
|
|
131
132
|
tooltip={tooltip}
|
|
132
133
|
hint={hint}
|
|
134
|
+
hintPosition={hintPosition}
|
|
133
135
|
space={fieldSpace}
|
|
134
136
|
feedback={feedback}
|
|
135
137
|
inactive={inactive}
|
|
@@ -205,6 +207,10 @@ ToggleSwitchGroup.propTypes = {
|
|
|
205
207
|
* Optional additional text giving more detail to help a user make a choice.
|
|
206
208
|
*/
|
|
207
209
|
hint: PropTypes.string,
|
|
210
|
+
/**
|
|
211
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
212
|
+
*/
|
|
213
|
+
hintPosition: PropTypes.oneOf(['inline', 'below']),
|
|
208
214
|
/**
|
|
209
215
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
210
216
|
*/
|