@telus-uds/components-base 3.23.0 → 3.25.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 (73) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/lib/cjs/Button/ButtonGroup.js +9 -2
  3. package/lib/cjs/Card/CardBase.js +97 -17
  4. package/lib/cjs/Card/PressableCardBase.js +12 -8
  5. package/lib/cjs/Carousel/Carousel.js +35 -4
  6. package/lib/cjs/FlexGrid/FlexGrid.js +31 -35
  7. package/lib/cjs/HorizontalScroll/HorizontalScroll.js +5 -2
  8. package/lib/cjs/Icon/Icon.js +3 -0
  9. package/lib/cjs/IconButton/IconButton.js +15 -5
  10. package/lib/cjs/Listbox/GroupControl.js +12 -6
  11. package/lib/cjs/Listbox/Listbox.js +41 -7
  12. package/lib/cjs/Listbox/ListboxGroup.js +139 -8
  13. package/lib/cjs/Listbox/ListboxOverlay.js +10 -5
  14. package/lib/cjs/Listbox/SecondLevelHeader.js +201 -0
  15. package/lib/cjs/Listbox/dictionary.js +14 -0
  16. package/lib/cjs/Shortcuts/Shortcuts.js +169 -0
  17. package/lib/cjs/Shortcuts/ShortcutsItem.js +280 -0
  18. package/lib/cjs/Shortcuts/index.js +16 -0
  19. package/lib/cjs/TextInput/TextInputBase.js +2 -3
  20. package/lib/cjs/Tooltip/Tooltip.native.js +2 -0
  21. package/lib/cjs/index.js +15 -0
  22. package/lib/cjs/utils/index.js +9 -1
  23. package/lib/cjs/utils/resolveContentMaxWidth.js +30 -0
  24. package/lib/esm/Button/ButtonGroup.js +9 -2
  25. package/lib/esm/Card/CardBase.js +97 -17
  26. package/lib/esm/Card/PressableCardBase.js +10 -8
  27. package/lib/esm/Carousel/Carousel.js +37 -6
  28. package/lib/esm/FlexGrid/FlexGrid.js +31 -35
  29. package/lib/esm/HorizontalScroll/HorizontalScroll.js +6 -3
  30. package/lib/esm/Icon/Icon.js +3 -0
  31. package/lib/esm/IconButton/IconButton.js +15 -5
  32. package/lib/esm/Listbox/GroupControl.js +12 -6
  33. package/lib/esm/Listbox/Listbox.js +41 -7
  34. package/lib/esm/Listbox/ListboxGroup.js +141 -10
  35. package/lib/esm/Listbox/ListboxOverlay.js +10 -5
  36. package/lib/esm/Listbox/SecondLevelHeader.js +194 -0
  37. package/lib/esm/Listbox/dictionary.js +8 -0
  38. package/lib/esm/Shortcuts/Shortcuts.js +160 -0
  39. package/lib/esm/Shortcuts/ShortcutsItem.js +273 -0
  40. package/lib/esm/Shortcuts/index.js +3 -0
  41. package/lib/esm/TextInput/TextInputBase.js +2 -3
  42. package/lib/esm/Tooltip/Tooltip.native.js +2 -0
  43. package/lib/esm/index.js +1 -0
  44. package/lib/esm/utils/index.js +2 -1
  45. package/lib/esm/utils/resolveContentMaxWidth.js +24 -0
  46. package/lib/package.json +2 -2
  47. package/package.json +2 -2
  48. package/src/Button/ButtonGroup.jsx +20 -3
  49. package/src/Card/CardBase.jsx +113 -14
  50. package/src/Card/PressableCardBase.jsx +17 -5
  51. package/src/Carousel/Carousel.jsx +38 -6
  52. package/src/FlexGrid/FlexGrid.jsx +30 -39
  53. package/src/HorizontalScroll/HorizontalScroll.jsx +6 -3
  54. package/src/Icon/Icon.jsx +3 -0
  55. package/src/IconButton/IconButton.jsx +12 -5
  56. package/src/Listbox/GroupControl.jsx +41 -33
  57. package/src/Listbox/Listbox.jsx +41 -2
  58. package/src/Listbox/ListboxGroup.jsx +158 -26
  59. package/src/Listbox/ListboxOverlay.jsx +18 -5
  60. package/src/Listbox/SecondLevelHeader.jsx +182 -0
  61. package/src/Listbox/dictionary.js +8 -0
  62. package/src/Shortcuts/Shortcuts.jsx +174 -0
  63. package/src/Shortcuts/ShortcutsItem.jsx +297 -0
  64. package/src/Shortcuts/index.js +4 -0
  65. package/src/TextInput/TextInputBase.jsx +2 -2
  66. package/src/Tooltip/Tooltip.native.jsx +2 -1
  67. package/src/index.js +1 -0
  68. package/src/utils/index.js +1 -0
  69. package/src/utils/resolveContentMaxWidth.js +28 -0
  70. package/types/Listbox.d.ts +24 -0
  71. package/types/Shortcuts.d.ts +136 -0
  72. package/types/Status.d.ts +42 -0
  73. package/types/index.d.ts +15 -0
@@ -0,0 +1,174 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { Platform, StyleSheet, View } from 'react-native'
4
+ import { viewports } from '@telus-uds/system-constants'
5
+
6
+ import { useTheme, useThemeTokens } from '../ThemeProvider'
7
+ import { useViewport } from '../ViewportProvider'
8
+ import {
9
+ a11yProps,
10
+ getTokensPropType,
11
+ selectSystemProps,
12
+ useResponsiveProp,
13
+ variantProp,
14
+ viewProps
15
+ } from '../utils'
16
+
17
+ import HorizontalScroll, {
18
+ horizontalScrollUtils,
19
+ HorizontalScrollButton
20
+ } from '../HorizontalScroll'
21
+
22
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
23
+
24
+ const { selectHorizontalScrollTokens, useItemPositions } = horizontalScrollUtils
25
+
26
+ const selectStyles = (themeTokens, maxWidth, viewport) => {
27
+ const isDesktop =
28
+ viewport === viewports.md || viewport === viewports.lg || viewport === viewports.xl
29
+
30
+ return {
31
+ wrapper: {
32
+ alignItems: isDesktop ? 'center' : 'flex-start'
33
+ },
34
+ scrollContainer: {
35
+ width: '100%',
36
+ ...(isDesktop && { maxWidth })
37
+ },
38
+ container: {
39
+ paddingTop: themeTokens.mainContainerTopPadding,
40
+ paddingBottom: themeTokens.mainContainerBottomPadding,
41
+ paddingLeft: themeTokens.mainContainerLeftPadding,
42
+ paddingRight: themeTokens.mainContainerRightPadding,
43
+ gap: themeTokens.mainContainerGap,
44
+ ...(isDesktop && {
45
+ alignItems: 'flex-start',
46
+ justifyContent: 'center'
47
+ })
48
+ }
49
+ }
50
+ }
51
+
52
+ /**
53
+ * A horizontal scrollable shortcuts component that displays a collection of shortcut items.
54
+ * This component automatically injects shared configuration props to all ShortcutsItem children
55
+ * via React.cloneElement, including variant settings, hideLabels, and iconVariant.
56
+ *
57
+ * @component
58
+ * @param {Object} props - Component properties
59
+ * @param {Object} [props.tokens] - Theme tokens to customize the component's appearance
60
+ * @param {Object} [props.variant] - Visual variant configuration for the shortcuts container and its items
61
+ * @param {string} [props.variant.width] - Width variant to apply to all items (e.g., 'equal', 'dynamic')
62
+ * @param {Object} [props.scrollButtonTokens] - Tokens to customize scroll button appearance
63
+ * @param {boolean} [props.hideLabels=false] - Whether to hide labels on all shortcut items (can be overridden per item)
64
+ * @param {Object} [props.iconVariant] - Icon variant to apply to all shortcut items (can be overridden per item)
65
+ * @param {React.ReactNode} props.children - ShortcutsItem components to render
66
+ * @param {React.Ref} ref - Forwarded ref to the component's root element
67
+ * @returns {React.ReactElement} Rendered shortcuts component with horizontal scroll functionality
68
+ *
69
+ * @example
70
+ * <Shortcuts hideLabels={false} variant={{ width: 'equal' }}>
71
+ * <ShortcutsItem icon={HomeIcon} label="Home" href="/home" />
72
+ * <ShortcutsItem icon={SettingsIcon} label="Settings" href="/settings" />
73
+ * </Shortcuts>
74
+ *
75
+ * @example
76
+ * // Item-level props override container props
77
+ * <Shortcuts hideLabels iconVariant={{ size: 'small' }}>
78
+ * <ShortcutsItem icon={HomeIcon} label="Home" hideLabel={false} />
79
+ * <ShortcutsItem icon={SettingsIcon} label="Settings" />
80
+ * </Shortcuts>
81
+ */
82
+ const Shortcuts = React.forwardRef(
83
+ (
84
+ { tokens, variant, scrollButtonTokens, hideLabels = false, iconVariant, children, ...rest },
85
+ ref
86
+ ) => {
87
+ const viewport = useViewport()
88
+ const themeTokens = useThemeTokens('Shortcuts', tokens, variant, {
89
+ viewport
90
+ })
91
+
92
+ const { themeOptions } = useTheme()
93
+ const maxWidth = useResponsiveProp(
94
+ themeOptions?.contentMaxWidth,
95
+ viewports.map.get(viewports.xl)
96
+ )
97
+
98
+ const [itemPositions] = useItemPositions()
99
+
100
+ const [maxItemWidth, setMaxItemWidth] = React.useState(null)
101
+
102
+ const registerWidth = React.useCallback(
103
+ (width) => setMaxItemWidth((prev) => (prev == null || width > prev ? width : prev)),
104
+ []
105
+ )
106
+
107
+ const styles = selectStyles(themeTokens, maxWidth, viewport)
108
+
109
+ const childrenWithProps = React.Children.map(children, (child) => {
110
+ if (!React.isValidElement(child)) {
111
+ return child
112
+ }
113
+ return React.cloneElement(child, {
114
+ maxWidth: maxItemWidth,
115
+ registerWidth,
116
+ containerVariant: variant,
117
+ containerHideLabels: hideLabels,
118
+ containerIconVariant: iconVariant
119
+ })
120
+ })
121
+
122
+ return (
123
+ <View style={[staticStyles.wrapper, styles.wrapper]} ref={ref} {...selectProps(rest)}>
124
+ <View style={styles.scrollContainer}>
125
+ <HorizontalScroll
126
+ ScrollButton={HorizontalScrollButton}
127
+ itemPositions={itemPositions}
128
+ tokens={selectHorizontalScrollTokens(themeTokens)}
129
+ scrollButtonTokens={scrollButtonTokens}
130
+ variant={{ hideNavigationButtons: Platform.OS !== 'web' }}
131
+ >
132
+ <View style={[staticStyles.container, styles.container]}>{childrenWithProps}</View>
133
+ </HorizontalScroll>
134
+ </View>
135
+ </View>
136
+ )
137
+ }
138
+ )
139
+
140
+ Shortcuts.displayName = 'Shortcuts'
141
+
142
+ Shortcuts.propTypes = {
143
+ ...selectedSystemPropTypes,
144
+ tokens: getTokensPropType('Shortcuts'),
145
+ variant: variantProp.propType,
146
+ /**
147
+ * Custom tokens for `HorizontalScrollButton`
148
+ */
149
+ scrollButtonTokens: getTokensPropType('HorizontalScrollButton'),
150
+ /**
151
+ * Hide labels for all ShortcutsItem children. When true, labels are visually hidden but remain accessible to screen readers via the icon's accessibilityLabel.
152
+ */
153
+ hideLabels: PropTypes.bool,
154
+ /**
155
+ * Icon variant to apply to all ShortcutsItem children.
156
+ */
157
+ iconVariant: variantProp.propType,
158
+ /**
159
+ * ShortcutsItem components to be rendered within the Shortcuts container
160
+ */
161
+ children: PropTypes.node
162
+ }
163
+
164
+ const staticStyles = StyleSheet.create({
165
+ wrapper: {
166
+ flexGrow: 1
167
+ },
168
+ container: {
169
+ flexDirection: 'row',
170
+ flex: 1
171
+ }
172
+ })
173
+
174
+ export default Shortcuts
@@ -0,0 +1,297 @@
1
+ import React from 'react'
2
+ import { Image, Platform, Pressable, StyleSheet, View } from 'react-native'
3
+ import PropTypes from 'prop-types'
4
+
5
+ import { applyTextStyles, useThemeTokensCallback } from '../ThemeProvider'
6
+ import {
7
+ a11yProps,
8
+ clickProps,
9
+ getTokensPropType,
10
+ hrefAttrsProp,
11
+ linkProps,
12
+ resolvePressableState,
13
+ selectSystemProps,
14
+ variantProp,
15
+ viewProps,
16
+ wrapStringsInText
17
+ } from '../utils'
18
+ import Icon from '../Icon'
19
+
20
+ const DYNAMIC_WIDTH_VARIANT = 'dynamic'
21
+ const EQUAL_WIDTH_VARIANT = 'equal'
22
+
23
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps])
24
+
25
+ const selectPressableStyles = (tokens, widthVariant, equalWidth) => {
26
+ const styles = {
27
+ borderColor: tokens.borderColor,
28
+ borderRadius: tokens.borderRadius,
29
+ borderWidth: tokens.borderWidth,
30
+ ...Platform.select({
31
+ web: {
32
+ outline: 'none'
33
+ }
34
+ })
35
+ }
36
+
37
+ if (widthVariant === DYNAMIC_WIDTH_VARIANT) {
38
+ styles.width = 'auto'
39
+ } else if (widthVariant === EQUAL_WIDTH_VARIANT) {
40
+ if (equalWidth) {
41
+ styles.width = equalWidth
42
+ } else {
43
+ styles.minWidth = tokens.width
44
+ }
45
+ } else {
46
+ styles.width = tokens.width
47
+ }
48
+
49
+ return styles
50
+ }
51
+
52
+ const selectIconContainerStyles = (tokens) => ({
53
+ paddingBottom: tokens.iconContainerPaddingBottom,
54
+ paddingLeft: tokens.iconContainerPaddingLeft,
55
+ paddingRight: tokens.iconContainerPaddingRight,
56
+ paddingTop: tokens.iconContainerPaddingTop
57
+ })
58
+
59
+ const selectIconVariant = () => ({
60
+ background: true,
61
+ padding: 'medium'
62
+ })
63
+
64
+ const selectIconTokens = (tokens) => ({
65
+ backgroundColor: tokens.iconBackgroundColor,
66
+ color: tokens.iconColor,
67
+ size: tokens.iconSize,
68
+ width: tokens.iconWidth
69
+ })
70
+
71
+ const selectImageStyles = (tokens) => ({
72
+ width: tokens.imageWidth,
73
+ height: tokens.imageHeight
74
+ })
75
+
76
+ const selectLabelContainerStyles = (tokens) => ({
77
+ paddingBottom: tokens.labelContainerPaddingBottom,
78
+ paddingLeft: tokens.labelContainerPaddingLeft,
79
+ paddingRight: tokens.labelContainerPaddingRight,
80
+ paddingTop: tokens.labelContainerPaddingTop
81
+ })
82
+
83
+ const selectTitleTextStyles = (tokens) =>
84
+ applyTextStyles({
85
+ fontColor: tokens.labelFontColor,
86
+ fontName: tokens.labelFontName,
87
+ fontSize: tokens.labelFontSize,
88
+ fontWeight: tokens.labelFontWeight,
89
+ lineHeight: tokens.labelLineHeight,
90
+ textDecorationLine: tokens.labelUnderline,
91
+ textAlign: tokens.labelTextAlign
92
+ })
93
+
94
+ /**
95
+ * A clickable shortcut item component that displays an icon or image with an optional label.
96
+ * Can be used within a Shortcuts container to create a grid of navigation shortcuts.
97
+ *
98
+ * @component
99
+ * @param {Object} props - Component props
100
+ * @param {string} [props.icon] - Icon identifier to display
101
+ * @param {Object} [props.image={ src: '', alt: '' }] - Image object with src and alt properties
102
+ * @param {string} [props.image.src] - Image source URL
103
+ * @param {string} [props.image.alt] - Image alt text for accessibility
104
+ * @param {string|React.ReactNode} props.label - Label text or content to display below the icon/image
105
+ * @param {boolean} [props.hideLabel=false] - Whether to hide the label for this specific item
106
+ * @param {string} [props.href] - Link URL for navigation
107
+ * @param {Object} [props.iconVariant] - Icon variant to apply to this specific item
108
+ * @param {Object} [props.tokens] - Theme tokens to customize appearance
109
+ * @param {Object} [props.variant] - Variant configuration object for this specific item
110
+ * @param {string} [props.variant.width] - Width variant (e.g., 'dynamic', 'equal')
111
+ * @param {Function} [props.onPressableStateChange] - Callback function that receives the pressable state object (pressed, hovered, focused)
112
+ * @param {number} [props.maxWidth] - Maximum width for equal width variant (injected by Shortcuts container)
113
+ * @param {Function} [props.registerWidth] - Callback to register width for equal width variant (injected by Shortcuts container)
114
+ * @param {Object} [props.containerVariant] - Variant configuration from Shortcuts container (injected by Shortcuts container)
115
+ * @param {boolean} [props.containerHideLabels] - Hide labels setting from Shortcuts container (injected by Shortcuts container)
116
+ * @param {Object} [props.containerIconVariant] - Icon variant from Shortcuts container (injected by Shortcuts container)
117
+ * @param {React.Ref} ref - Forwarded ref to the Pressable component
118
+ * @returns {React.ReactElement} The rendered shortcut item
119
+ *
120
+ * @example
121
+ * <ShortcutsItem
122
+ * icon={HomeIcon}
123
+ * label="Home"
124
+ * href="/home"
125
+ * onPressableStateChange={(state) => console.log(state)}
126
+ * />
127
+ */
128
+ const ShortcutsItem = React.forwardRef(
129
+ (
130
+ {
131
+ icon,
132
+ image = { src: '', alt: '' },
133
+ label,
134
+ hideLabel = false,
135
+ href,
136
+ iconVariant,
137
+ tokens,
138
+ variant,
139
+ onPressableStateChange,
140
+ maxWidth,
141
+ registerWidth,
142
+ containerVariant,
143
+ containerHideLabels,
144
+ containerIconVariant,
145
+ ...rest
146
+ },
147
+ ref
148
+ ) => {
149
+ const mergedVariant = { ...containerVariant, ...variant }
150
+ const widthVariant = mergedVariant?.width
151
+ const shouldHideLabel = hideLabel || containerHideLabels
152
+ const mergedIconVariant = iconVariant ?? containerIconVariant
153
+
154
+ const getThemeTokens = useThemeTokensCallback('ShortcutsItem', tokens, mergedVariant)
155
+ const getTokens = (pressableState) => getThemeTokens(resolvePressableState(pressableState))
156
+
157
+ const { onPress, ...props } = clickProps.toPressProps(rest)
158
+ const { hrefAttrs, rawRest } = hrefAttrsProp.bundle(props)
159
+ const selectedProps = selectProps({
160
+ href,
161
+ onPress: linkProps.handleHref({ href, onPress }),
162
+ hrefAttrs,
163
+ ...rawRest
164
+ })
165
+
166
+ const handleLayout = (event) => {
167
+ if (widthVariant === EQUAL_WIDTH_VARIANT && registerWidth) {
168
+ const { width } = event.nativeEvent.layout
169
+ registerWidth(width)
170
+ }
171
+ }
172
+
173
+ return (
174
+ <Pressable
175
+ ref={ref}
176
+ style={(pressableState) =>
177
+ selectPressableStyles(getTokens(pressableState), widthVariant, maxWidth)
178
+ }
179
+ onLayout={handleLayout}
180
+ {...selectedProps}
181
+ >
182
+ {(pressableState) => {
183
+ const themeTokens = getTokens(pressableState)
184
+
185
+ if (onPressableStateChange) {
186
+ onPressableStateChange(resolvePressableState(pressableState))
187
+ }
188
+
189
+ return (
190
+ <View style={staticStyles.container}>
191
+ {icon && (
192
+ <View style={selectIconContainerStyles(themeTokens)}>
193
+ <Icon
194
+ icon={icon}
195
+ variant={mergedIconVariant ?? selectIconVariant()}
196
+ tokens={mergedIconVariant ? {} : selectIconTokens(themeTokens)}
197
+ {...(Platform.OS === 'web' && { accessibilityLabel: label })}
198
+ />
199
+ </View>
200
+ )}
201
+ {!icon && image && (
202
+ <Image
203
+ source={image.src}
204
+ alt={image.alt}
205
+ style={selectImageStyles(themeTokens)}
206
+ resizeMethod="resize"
207
+ accessibilityIgnoresInvertColors
208
+ />
209
+ )}
210
+ {label && !shouldHideLabel && (
211
+ <View style={[staticStyles.label, selectLabelContainerStyles(themeTokens)]}>
212
+ {wrapStringsInText(label, { style: selectTitleTextStyles(themeTokens) })}
213
+ </View>
214
+ )}
215
+ </View>
216
+ )
217
+ }}
218
+ </Pressable>
219
+ )
220
+ }
221
+ )
222
+
223
+ ShortcutsItem.displayName = 'ShortcutsItem'
224
+
225
+ ShortcutsItem.propTypes = {
226
+ ...selectedSystemPropTypes,
227
+ tokens: getTokensPropType('ShortcutsItem'),
228
+ variant: variantProp.propType,
229
+ /**
230
+ * Icon for the ShortcutsItem
231
+ */
232
+ icon: PropTypes.elementType,
233
+ /**
234
+ * Image for the ShortcutsItem
235
+ */
236
+ image: PropTypes.shape({
237
+ src: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
238
+ alt: PropTypes.string
239
+ }),
240
+ /**
241
+ * Label for the ShortcutsItem
242
+ */
243
+ label: PropTypes.string,
244
+ /**
245
+ * Hide the label for this specific ShortcutsItem. When true, the label is visually hidden but remains accessible to screen readers via the icon's accessibilityLabel.
246
+ */
247
+ hideLabel: PropTypes.bool,
248
+ /**
249
+ * href for the ShortcutsItem
250
+ */
251
+ href: PropTypes.string,
252
+ /**
253
+ * Icon variant for this specific ShortcutsItem
254
+ */
255
+ iconVariant: variantProp.propType,
256
+ /**
257
+ * Callback function that receives the pressable state object containing pressed, hovered, and focused boolean properties
258
+ */
259
+ onPressableStateChange: PropTypes.func,
260
+ /**
261
+ * Maximum width for equal width variant (automatically injected by Shortcuts container)
262
+ * @private
263
+ */
264
+ maxWidth: PropTypes.number,
265
+ /**
266
+ * Callback to register width for equal width variant (automatically injected by Shortcuts container)
267
+ * @private
268
+ */
269
+ registerWidth: PropTypes.func,
270
+ /**
271
+ * Variant configuration from Shortcuts container (automatically injected by Shortcuts container)
272
+ * @private
273
+ */
274
+ containerVariant: variantProp.propType,
275
+ /**
276
+ * Hide labels setting from Shortcuts container (automatically injected by Shortcuts container)
277
+ * @private
278
+ */
279
+ containerHideLabels: PropTypes.bool,
280
+ /**
281
+ * Icon variant from Shortcuts container (automatically injected by Shortcuts container)
282
+ * @private
283
+ */
284
+ containerIconVariant: variantProp.propType
285
+ }
286
+
287
+ const staticStyles = StyleSheet.create({
288
+ container: {
289
+ alignItems: 'center',
290
+ justifyContent: 'center'
291
+ },
292
+ label: {
293
+ flexWrap: 'wrap'
294
+ }
295
+ })
296
+
297
+ export default ShortcutsItem
@@ -0,0 +1,4 @@
1
+ import Shortcuts from './Shortcuts'
2
+
3
+ export { default as ShortcutsItem } from './ShortcutsItem'
4
+ export default Shortcuts
@@ -313,7 +313,7 @@ const TextInputBase = React.forwardRef(
313
313
  icon={ClearButtonIcon}
314
314
  key="clear"
315
315
  onPress={handleClear}
316
- variant={{ compact: true }}
316
+ variant={{ subtle: true }}
317
317
  />
318
318
  )
319
319
  }
@@ -329,7 +329,7 @@ const TextInputBase = React.forwardRef(
329
329
  icon={!showPassword ? passwordShowButtonIcon : passwordHideButtonIcon}
330
330
  key={!showPassword ? 'hide' : 'show'}
331
331
  onPress={handleShowOrHide}
332
- variant={{ compact: true, password: true, inactive: variant.inactive, size: 'large' }}
332
+ variant={{ subtle: true, inactive: variant.inactive, size: 'large' }}
333
333
  tokens={{ width: 40, height: 40 }}
334
334
  />
335
335
  )
@@ -127,12 +127,12 @@ const Tooltip = React.forwardRef(
127
127
  nativeID,
128
128
  activateOnHover = false,
129
129
  tooltipButtonTokens,
130
+ testID,
130
131
  ...rest
131
132
  },
132
133
  ref
133
134
  ) => {
134
135
  const [isOpen, setIsOpen] = React.useState(false)
135
-
136
136
  const controlRef = React.useRef()
137
137
  const [controlLayout, setControlLayout] = React.useState(null)
138
138
  const [tooltipDimensions, setTooltipDimensions] = React.useState(null)
@@ -276,6 +276,7 @@ const Tooltip = React.forwardRef(
276
276
  }
277
277
  })
278
278
  ]}
279
+ testID={testID}
279
280
  {...selectProps(rest)}
280
281
  >
281
282
  <Pressable
package/src/index.js CHANGED
@@ -51,6 +51,7 @@ export { default as RadioCard, RadioCardGroup } from './RadioCard'
51
51
  export { default as Responsive } from './Responsive'
52
52
  export { default as Search } from './Search'
53
53
  export { default as Select } from './Select'
54
+ export { default as Shortcuts, ShortcutsItem } from './Shortcuts'
54
55
  export { default as SideNav } from './SideNav'
55
56
  export { default as Skeleton } from './Skeleton'
56
57
  export { default as SkipLink } from './SkipLink'
@@ -27,3 +27,4 @@ export { default as formatImageSource } from './formatImageSource'
27
27
  export { default as getSpacingScale } from './getSpacingScale'
28
28
  export { default as useVariants } from './useVariants'
29
29
  export { default as isTouchDevice } from './isTouchDevice'
30
+ export { default as resolveContentMaxWidth } from './resolveContentMaxWidth'
@@ -0,0 +1,28 @@
1
+ const CONTENT_MAX_WIDTH = 'max'
2
+ const CONTENT_FULL_WIDTH = 'full'
3
+
4
+ /**
5
+ * Resolves the maximum width for content based on the provided value and responsive width.
6
+ *
7
+ * @param {number|string|null|undefined} contentMaxWidthValue - The maximum width value for the content.
8
+ * Can be a number, a special string constant (e.g., CONTENT_FULL_WIDTH, CONTENT_MAX_WIDTH), or null/undefined.
9
+ * @param {number} responsiveWidth - The responsive width to use when contentMaxWidthValue is CONTENT_MAX_WIDTH.
10
+ * @returns {number|string|null} The resolved maximum width value, or null if full width is desired.
11
+ */
12
+ const resolveContentMaxWidth = (contentMaxWidthValue, responsiveWidth) => {
13
+ if (!contentMaxWidthValue || contentMaxWidthValue === CONTENT_FULL_WIDTH) {
14
+ return null
15
+ }
16
+
17
+ if (Number.isFinite(contentMaxWidthValue)) {
18
+ return contentMaxWidthValue
19
+ }
20
+
21
+ if (contentMaxWidthValue === CONTENT_MAX_WIDTH) {
22
+ return responsiveWidth
23
+ }
24
+
25
+ return contentMaxWidthValue
26
+ }
27
+
28
+ export default resolveContentMaxWidth
@@ -40,6 +40,29 @@ type ListboxTokens = {
40
40
  itemHeight?: number
41
41
  groupHeight?: number
42
42
  lineHeight?: number
43
+ secondLevelHeaderBackgroundColor?: string
44
+ secondLevelHeaderPaddingTop?: number
45
+ secondLevelHeaderPaddingBottom?: number
46
+ secondLevelHeaderPaddingLeft?: number
47
+ secondLevelHeaderPaddingRight?: number
48
+ secondLevelBackIcon?: string
49
+ secondLevelBackIconColor?: string
50
+ secondLevelBackIconSize?: number
51
+ secondLevelBackLinkColor?: string
52
+ secondLevelBackLinkFontSize?: number
53
+ secondLevelBackLinkFontName?: string
54
+ secondLevelBackLinkFontWeight?: string
55
+ secondLevelCloseIcon?: string
56
+ secondLevelCloseIconColor?: string
57
+ secondLevelCloseIconSize?: number
58
+ secondLevelCloseButtonBackgroundColor?: string
59
+ secondLevelCloseButtonBorderColor?: string
60
+ secondLevelCloseButtonBorderWidth?: number | string
61
+ secondLevelCloseButtonBorderRadius?: number | string
62
+ secondLevelCloseButtonPadding?: number
63
+ secondLevelDividerColor?: string
64
+ secondLevelDividerWidth?: number
65
+ secondLevelParentIcon?: string
43
66
  }
44
67
 
45
68
  type ListboxItems = {
@@ -55,6 +78,7 @@ export interface ListboxProps {
55
78
  LinkRouter?: React.ElementType
56
79
  linkRouterProps?: object
57
80
  tokens?: ListboxTokens
81
+ variant?: { secondLevel?: boolean }
58
82
  selectedId?: string
59
83
  onClose?: () => void
60
84
  }