@telus-uds/components-base 0.0.2-prerelease.9 → 1.0.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 (282) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.ultra.cache.json +1 -1
  3. package/CHANGELOG.md +32 -0
  4. package/README.md +4 -2
  5. package/__fixtures__/test-utils.js +25 -0
  6. package/__fixtures__/testTheme.js +4 -2
  7. package/__tests__/Button/ButtonGroup.test.jsx +4 -5
  8. package/__tests__/Checkbox/Checkbox.test.jsx +2 -2
  9. package/__tests__/Checkbox/CheckboxGroup.test.jsx +4 -5
  10. package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
  11. package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
  12. package/__tests__/Link/LinkBase.test.jsx +0 -14
  13. package/__tests__/Radio/Radio.test.jsx +2 -2
  14. package/__tests__/Radio/RadioGroup.test.jsx +4 -5
  15. package/__tests__/RadioCard/RadioCard.test.jsx +2 -2
  16. package/__tests__/RadioCard/RadioCardGroup.test.jsx +4 -5
  17. package/__tests__/Search/Search.test.jsx +9 -8
  18. package/__tests__/Select/Select.test.jsx +3 -2
  19. package/__tests__/Tabs/Tabs.test.jsx +1 -161
  20. package/__tests__/Tags/Tags.test.jsx +4 -5
  21. package/__tests__/TextInput/TextArea.test.jsx +3 -2
  22. package/__tests__/TextInput/TextInputBase.test.jsx +10 -5
  23. package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
  24. package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
  25. package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  26. package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
  27. package/__tests__/utils/children.test.jsx +128 -0
  28. package/__tests__/utils/input.test.js +1 -1
  29. package/__tests__/utils/semantics.test.jsx +43 -0
  30. package/lib/A11yText/index.js +10 -5
  31. package/lib/ActivityIndicator/Spinner.js +16 -13
  32. package/lib/ActivityIndicator/Spinner.native.js +12 -8
  33. package/lib/Box/Box.js +102 -8
  34. package/lib/Button/Button.js +9 -8
  35. package/lib/Button/ButtonBase.js +14 -7
  36. package/lib/Button/ButtonGroup.js +25 -10
  37. package/lib/Button/ButtonLink.js +10 -7
  38. package/lib/Card/Card.js +2 -0
  39. package/lib/Card/CardBase.js +12 -5
  40. package/lib/Card/PressableCardBase.js +12 -8
  41. package/lib/Checkbox/Checkbox.js +25 -14
  42. package/lib/Checkbox/CheckboxGroup.js +22 -12
  43. package/lib/Divider/Divider.js +12 -7
  44. package/lib/ExpandCollapse/Accordion.js +10 -4
  45. package/lib/ExpandCollapse/Control.js +12 -6
  46. package/lib/ExpandCollapse/ExpandCollapse.js +10 -5
  47. package/lib/ExpandCollapse/Panel.js +8 -7
  48. package/lib/Feedback/Feedback.js +10 -5
  49. package/lib/Fieldset/Fieldset.js +10 -5
  50. package/lib/Fieldset/FieldsetContainer.js +10 -5
  51. package/lib/Fieldset/FieldsetContainer.native.js +10 -5
  52. package/lib/Fieldset/Legend.js +10 -5
  53. package/lib/Fieldset/Legend.native.js +10 -5
  54. package/lib/FlexGrid/Col/Col.js +8 -5
  55. package/lib/FlexGrid/FlexGrid.js +31 -6
  56. package/lib/FlexGrid/Row/Row.js +12 -5
  57. package/lib/{Tabs → HorizontalScroll}/HorizontalScroll.js +5 -4
  58. package/lib/{Tabs/TabsScrollButton.js → HorizontalScroll/HorizontalScrollButton.js} +14 -8
  59. package/lib/{Tabs → HorizontalScroll}/ScrollViewEnd.js +0 -0
  60. package/lib/{Tabs → HorizontalScroll}/ScrollViewEnd.native.js +0 -0
  61. package/lib/{Tabs → HorizontalScroll}/dictionary.js +0 -0
  62. package/lib/HorizontalScroll/index.js +35 -0
  63. package/lib/{Tabs → HorizontalScroll}/itemPositions.js +0 -0
  64. package/lib/Icon/Icon.js +16 -9
  65. package/lib/Icon/IconText.js +8 -7
  66. package/lib/IconButton/IconButton.js +10 -5
  67. package/lib/InputLabel/InputLabel.js +33 -5
  68. package/lib/InputLabel/LabelContent.js +22 -12
  69. package/lib/InputLabel/LabelContent.native.js +23 -5
  70. package/lib/InputSupports/InputSupports.js +10 -5
  71. package/lib/Link/ChevronLink.js +12 -5
  72. package/lib/Link/InlinePressable.js +10 -4
  73. package/lib/Link/InlinePressable.native.js +5 -4
  74. package/lib/Link/Link.js +12 -5
  75. package/lib/Link/LinkBase.js +12 -5
  76. package/lib/Link/TextButton.js +10 -5
  77. package/lib/List/List.js +5 -4
  78. package/lib/List/ListItem.js +16 -8
  79. package/lib/Modal/Modal.js +10 -5
  80. package/lib/Notification/Notification.js +21 -5
  81. package/lib/Pagination/PageButton.js +21 -10
  82. package/lib/Pagination/Pagination.js +12 -7
  83. package/lib/Pagination/SideButton.js +12 -7
  84. package/lib/Pagination/usePagination.js +2 -2
  85. package/lib/Progress/Progress.js +10 -5
  86. package/lib/Progress/ProgressBar.js +21 -10
  87. package/lib/Progress/ProgressBarBackground.js +12 -8
  88. package/lib/Radio/Radio.js +14 -13
  89. package/lib/Radio/RadioButton.js +20 -9
  90. package/lib/Radio/RadioGroup.js +24 -13
  91. package/lib/RadioCard/RadioCard.js +14 -10
  92. package/lib/RadioCard/RadioCardGroup.js +13 -12
  93. package/lib/Search/Search.js +29 -18
  94. package/lib/Select/Picker.js +11 -6
  95. package/lib/Select/Picker.native.js +21 -6
  96. package/lib/Select/Select.js +46 -4
  97. package/lib/SideNav/Item.js +10 -5
  98. package/lib/SideNav/ItemsGroup.js +10 -5
  99. package/lib/SideNav/SideNav.js +11 -7
  100. package/lib/Skeleton/Skeleton.js +15 -15
  101. package/lib/Skeleton/skeletonWebAnimation.js +1 -1
  102. package/lib/Spacer/Spacer.js +19 -7
  103. package/lib/StackView/StackView.js +25 -7
  104. package/lib/StackView/StackWrap.js +16 -9
  105. package/lib/StackView/StackWrapBox.js +33 -8
  106. package/lib/StackView/StackWrapGap.js +16 -7
  107. package/lib/StackView/common.js +4 -2
  108. package/lib/StackView/getStackedContent.js +2 -2
  109. package/lib/StepTracker/StepTracker.js +10 -5
  110. package/lib/Tabs/Tabs.js +26 -19
  111. package/lib/Tabs/TabsItem.js +16 -12
  112. package/lib/Tags/Tags.js +27 -11
  113. package/lib/TextInput/TextArea.js +7 -5
  114. package/lib/TextInput/TextInput.js +12 -6
  115. package/lib/TextInput/TextInputBase.js +12 -8
  116. package/lib/ThemeProvider/ThemeProvider.js +14 -10
  117. package/lib/ThemeProvider/useSetTheme.js +6 -1
  118. package/lib/ThemeProvider/utils/styles.js +2 -2
  119. package/lib/ThemeProvider/utils/theme-tokens.js +39 -8
  120. package/lib/ToggleSwitch/ToggleSwitch.js +11 -6
  121. package/lib/Tooltip/Backdrop.js +10 -2
  122. package/lib/Tooltip/Tooltip.js +5 -4
  123. package/lib/Typography/Typography.js +40 -24
  124. package/lib/index.js +21 -0
  125. package/lib/utils/a11y/index.js +13 -0
  126. package/lib/utils/a11y/semantics.js +173 -0
  127. package/lib/utils/animation/useVerticalExpandAnimation.js +1 -1
  128. package/lib/utils/children.js +55 -8
  129. package/lib/utils/input.js +27 -17
  130. package/lib/utils/propTypes.js +82 -29
  131. package/lib/utils/useCopy.js +1 -1
  132. package/lib/utils/useHash.js +8 -4
  133. package/lib/utils/useSpacingScale.js +1 -3
  134. package/lib/utils/useUniqueId.js +1 -1
  135. package/package.json +9 -5
  136. package/release-context.json +4 -4
  137. package/src/A11yText/index.jsx +6 -4
  138. package/src/ActivityIndicator/Spinner.jsx +5 -3
  139. package/src/ActivityIndicator/Spinner.native.jsx +5 -3
  140. package/src/Box/Box.jsx +124 -39
  141. package/src/Button/Button.jsx +7 -4
  142. package/src/Button/ButtonBase.jsx +86 -77
  143. package/src/Button/ButtonGroup.jsx +81 -69
  144. package/src/Button/ButtonLink.jsx +18 -13
  145. package/src/Card/Card.jsx +2 -2
  146. package/src/Card/CardBase.jsx +5 -4
  147. package/src/Card/PressableCardBase.jsx +71 -64
  148. package/src/Checkbox/Checkbox.jsx +118 -108
  149. package/src/Checkbox/CheckboxGroup.jsx +72 -62
  150. package/src/Divider/Divider.jsx +7 -4
  151. package/src/ExpandCollapse/Accordion.jsx +3 -2
  152. package/src/ExpandCollapse/Control.jsx +40 -43
  153. package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
  154. package/src/ExpandCollapse/Panel.jsx +69 -63
  155. package/src/Feedback/Feedback.jsx +36 -33
  156. package/src/Fieldset/Fieldset.jsx +63 -56
  157. package/src/Fieldset/FieldsetContainer.jsx +14 -5
  158. package/src/Fieldset/FieldsetContainer.native.jsx +7 -4
  159. package/src/Fieldset/Legend.jsx +7 -2
  160. package/src/Fieldset/Legend.native.jsx +7 -2
  161. package/src/FlexGrid/Col/Col.jsx +139 -132
  162. package/src/FlexGrid/FlexGrid.jsx +79 -51
  163. package/src/FlexGrid/Row/Row.jsx +55 -48
  164. package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
  165. package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
  166. package/src/{Tabs → HorizontalScroll}/ScrollViewEnd.jsx +0 -0
  167. package/src/{Tabs → HorizontalScroll}/ScrollViewEnd.native.jsx +0 -0
  168. package/src/{Tabs → HorizontalScroll}/dictionary.js +0 -0
  169. package/src/HorizontalScroll/index.js +17 -0
  170. package/src/{Tabs → HorizontalScroll}/itemPositions.js +0 -0
  171. package/src/Icon/Icon.jsx +37 -35
  172. package/src/Icon/IconText.jsx +22 -17
  173. package/src/IconButton/IconButton.jsx +49 -42
  174. package/src/InputLabel/InputLabel.jsx +53 -38
  175. package/src/InputLabel/LabelContent.jsx +14 -6
  176. package/src/InputLabel/LabelContent.native.jsx +11 -2
  177. package/src/InputSupports/InputSupports.jsx +29 -34
  178. package/src/Link/ChevronLink.jsx +26 -16
  179. package/src/Link/InlinePressable.jsx +5 -3
  180. package/src/Link/InlinePressable.native.jsx +5 -3
  181. package/src/Link/Link.jsx +22 -16
  182. package/src/Link/LinkBase.jsx +67 -58
  183. package/src/Link/TextButton.jsx +30 -23
  184. package/src/List/List.jsx +5 -4
  185. package/src/List/ListItem.jsx +77 -82
  186. package/src/Modal/Modal.jsx +9 -4
  187. package/src/Notification/Notification.jsx +58 -43
  188. package/src/Pagination/PageButton.jsx +42 -35
  189. package/src/Pagination/Pagination.jsx +88 -92
  190. package/src/Pagination/SideButton.jsx +44 -41
  191. package/src/Progress/Progress.jsx +5 -4
  192. package/src/Progress/ProgressBar.jsx +42 -29
  193. package/src/Progress/ProgressBarBackground.jsx +5 -3
  194. package/src/Radio/Radio.jsx +85 -78
  195. package/src/Radio/RadioButton.jsx +54 -43
  196. package/src/Radio/RadioGroup.jsx +74 -63
  197. package/src/RadioCard/RadioCard.jsx +75 -68
  198. package/src/RadioCard/RadioCardGroup.jsx +82 -75
  199. package/src/Search/Search.jsx +127 -106
  200. package/src/Select/Picker.jsx +49 -42
  201. package/src/Select/Picker.native.jsx +56 -49
  202. package/src/Select/Select.jsx +115 -72
  203. package/src/SideNav/Item.jsx +53 -46
  204. package/src/SideNav/ItemsGroup.jsx +50 -43
  205. package/src/SideNav/SideNav.jsx +68 -60
  206. package/src/Skeleton/Skeleton.jsx +9 -13
  207. package/src/Spacer/Spacer.jsx +11 -4
  208. package/src/StackView/StackView.jsx +46 -23
  209. package/src/StackView/StackWrap.jsx +7 -6
  210. package/src/StackView/StackWrapBox.jsx +61 -28
  211. package/src/StackView/StackWrapGap.jsx +46 -24
  212. package/src/StackView/common.jsx +3 -2
  213. package/src/StepTracker/StepTracker.jsx +73 -62
  214. package/src/Tabs/Tabs.jsx +70 -62
  215. package/src/Tabs/TabsItem.jsx +111 -103
  216. package/src/Tags/Tags.jsx +114 -102
  217. package/src/TextInput/TextArea.jsx +5 -4
  218. package/src/TextInput/TextInput.jsx +5 -4
  219. package/src/TextInput/TextInputBase.jsx +84 -77
  220. package/src/ThemeProvider/ThemeProvider.jsx +11 -7
  221. package/src/ThemeProvider/useSetTheme.js +4 -0
  222. package/src/ThemeProvider/utils/theme-tokens.js +28 -0
  223. package/src/ToggleSwitch/ToggleSwitch.jsx +49 -50
  224. package/src/Tooltip/Tooltip.jsx +134 -130
  225. package/src/Typography/Typography.jsx +67 -44
  226. package/src/index.js +2 -0
  227. package/src/utils/a11y/index.js +1 -0
  228. package/src/utils/a11y/semantics.js +162 -0
  229. package/src/utils/children.jsx +60 -7
  230. package/src/utils/input.js +20 -17
  231. package/src/utils/propTypes.js +101 -39
  232. package/src/utils/useCopy.js +1 -1
  233. package/src/utils/useHash.js +8 -3
  234. package/stories/A11yText/A11yText.stories.jsx +2 -2
  235. package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +1 -1
  236. package/stories/Box/Box.stories.jsx +1 -1
  237. package/stories/Button/Button.stories.jsx +2 -2
  238. package/stories/Button/ButtonGroup.stories.jsx +1 -1
  239. package/stories/Button/ButtonLink.stories.jsx +1 -1
  240. package/stories/Card/Card.stories.jsx +1 -1
  241. package/stories/Checkbox/Checkbox.stories.jsx +1 -1
  242. package/stories/Divider/Divider.stories.jsx +1 -1
  243. package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +2 -2
  244. package/stories/Feedback/Feedback.stories.jsx +1 -1
  245. package/stories/FlexGrid/01 FlexGrid.stories.jsx +1 -1
  246. package/stories/FlexGrid/02 Row.stories.jsx +1 -1
  247. package/stories/FlexGrid/03 Col.stories.jsx +1 -1
  248. package/stories/Icon/Icon.stories.jsx +1 -1
  249. package/stories/IconButton/IconButton.stories.jsx +1 -1
  250. package/stories/InputLabel/InputLabel.stories.jsx +1 -1
  251. package/stories/Link/ChevronLink.stories.jsx +1 -1
  252. package/stories/Link/Link.stories.jsx +1 -1
  253. package/stories/Link/TextButton.stories.jsx +1 -1
  254. package/stories/List/List.stories.jsx +1 -1
  255. package/stories/Modal/Modal.stories.jsx +1 -1
  256. package/stories/Notification/Notification.stories.jsx +1 -1
  257. package/stories/Pagination/Pagination.stories.jsx +1 -1
  258. package/stories/Progress/Progress.stories.jsx +1 -1
  259. package/stories/Radio/Radio.stories.jsx +1 -1
  260. package/stories/RadioCard/RadioCard.stories.jsx +1 -1
  261. package/stories/Search/Search.stories.jsx +1 -1
  262. package/stories/Select/Select.stories.jsx +1 -1
  263. package/stories/SideNav/SideNav.stories.jsx +1 -1
  264. package/stories/SideNav/SideNavItem.stories.jsx +1 -1
  265. package/stories/SideNav/SideNavItemsGroup.stories.jsx +1 -1
  266. package/stories/Skeleton/Skeleton.stories.jsx +2 -2
  267. package/stories/Spacer/Spacer.stories.jsx +1 -1
  268. package/stories/StackView/StackView.stories.jsx +1 -1
  269. package/stories/StackView/StackWrap.stories.jsx +1 -1
  270. package/stories/StepTracker/StepTracker.stories.jsx +1 -1
  271. package/stories/Tabs/Tabs.stories.jsx +1 -1
  272. package/stories/Tags/Tags.stories.jsx +1 -1
  273. package/stories/TextInput/TextArea.stories.jsx +1 -1
  274. package/stories/TextInput/TextInput.stories.jsx +1 -1
  275. package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +1 -1
  276. package/stories/Tooltip/Tooltip.stories.jsx +1 -1
  277. package/stories/TooltipButton/TooltipButton.stories.jsx +1 -1
  278. package/stories/Typography/Typography.stories.jsx +1 -1
  279. package/stories/platform-supports.jsx +1 -1
  280. package/stories/supports.jsx +2 -2
  281. package/src/Tabs/HorizontalScroll.jsx +0 -165
  282. package/src/Tabs/TabsScrollButton.jsx +0 -100
@@ -1,5 +1,6 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
+ import ABBPropTypes from 'airbnb-prop-types'
3
4
  import { Platform } from 'react-native'
4
5
 
5
6
  import ButtonBase from './ButtonBase'
@@ -16,81 +17,88 @@ import {
16
17
  import { useMultipleInputValues } from '../utils/input'
17
18
  import { getPressHandlersWithArgs } from '../utils/pressability'
18
19
 
19
- const ButtonGroup = ({
20
- variant,
21
- tokens,
22
- items = [],
23
- values,
24
- initialValues,
25
- maxValues = 1,
26
- onChange,
27
- readOnly = false,
28
- inactive = false,
29
- accessibilityRole = maxValues === 1
30
- ? 'radiogroup' // radiogroup is cross-platform; only web aria has generic groups
31
- : Platform.select({ web: 'group', default: 'none' }),
32
- ...rest
33
- }) => {
34
- const viewport = useViewport()
35
- const themeTokens = useThemeTokens('ButtonGroup', tokens, variant, { viewport })
36
- const stackTokens = selectTokens('StackView', themeTokens)
37
- const { direction, space } = themeTokens
20
+ const ButtonGroup = forwardRef(
21
+ (
22
+ {
23
+ variant,
24
+ tokens,
25
+ items = [],
26
+ values,
27
+ initialValues,
28
+ maxValues = 1,
29
+ onChange,
30
+ readOnly = false,
31
+ inactive = false,
32
+ accessibilityRole = maxValues === 1
33
+ ? 'radiogroup' // radiogroup is cross-platform; only web aria has generic groups
34
+ : Platform.select({ web: 'group', default: 'none' }),
35
+ ...rest
36
+ },
37
+ ref
38
+ ) => {
39
+ const viewport = useViewport()
40
+ const themeTokens = useThemeTokens('ButtonGroup', tokens, variant, { viewport })
41
+ const stackTokens = selectTokens('StackView', themeTokens)
42
+ const { direction, space } = themeTokens
38
43
 
39
- const getButtonTokens = useThemeTokensCallback('ButtonGroupItem', tokens, variant)
44
+ const getButtonTokens = useThemeTokensCallback('ButtonGroupItem', tokens, variant)
40
45
 
41
- const { currentValues, toggleOneValue } = useMultipleInputValues({
42
- initialValues,
43
- values,
44
- maxValues,
45
- onChange,
46
- readOnly
47
- })
46
+ const { currentValues, toggleOneValue } = useMultipleInputValues({
47
+ initialValues,
48
+ values,
49
+ maxValues,
50
+ onChange,
51
+ readOnly
52
+ })
48
53
 
49
- const a11y = a11yProps.select({
50
- accessibilityRole,
51
- ...rest
52
- })
53
- const itemA11yRole = a11y.accessibilityRole === 'radiogroup' ? 'radio' : 'checkbox'
54
+ const a11y = a11yProps.select({
55
+ accessibilityRole,
56
+ ...rest
57
+ })
58
+ const itemA11yRole = a11y.accessibilityRole === 'radiogroup' ? 'radio' : 'checkbox'
54
59
 
55
- return (
56
- <StackWrap {...a11y} space={space} direction={direction} tokens={stackTokens}>
57
- {items.map(({ label, id = label, accessibilityLabel }, index) => {
58
- const isSelected = currentValues.includes(id)
60
+ return (
61
+ <StackWrap {...a11y} space={space} direction={direction} tokens={stackTokens} ref={ref}>
62
+ {items.map(({ label, id = label, accessibilityLabel, ref: itemRef }, index) => {
63
+ const isSelected = currentValues.includes(id)
59
64
 
60
- // Pass an object of relevant component state as first argument for any passed-in press handlers
61
- const pressHandlers = getPressHandlersWithArgs(rest, [{ id, label, currentValues }])
65
+ // Pass an object of relevant component state as first argument for any passed-in press handlers
66
+ const pressHandlers = getPressHandlersWithArgs(rest, [{ id, label, currentValues }])
62
67
 
63
- const handlePress = () => {
64
- if (pressHandlers.onPress) pressHandlers.onPress()
65
- toggleOneValue(id)
66
- }
68
+ const handlePress = (event) => {
69
+ if (pressHandlers.onPress) pressHandlers.onPress()
70
+ toggleOneValue(id, event)
71
+ }
67
72
 
68
- const itemA11y = {
69
- accessibilityState: { checked: isSelected },
70
- accessibilityRole: itemA11yRole,
71
- accessibilityLabel,
72
- ...a11yProps.getPositionInSet(items.length, index)
73
- }
73
+ const itemA11y = {
74
+ accessibilityState: { checked: isSelected },
75
+ accessibilityRole: itemA11yRole,
76
+ accessibilityLabel,
77
+ ...a11yProps.getPositionInSet(items.length, index)
78
+ }
74
79
 
75
- // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
76
- // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
77
- return (
78
- <ButtonBase
79
- key={id}
80
- {...pressHandlers}
81
- onPress={handlePress}
82
- tokens={getButtonTokens}
83
- selected={isSelected}
84
- inactive={inactive}
85
- {...itemA11y}
86
- >
87
- {label}
88
- </ButtonBase>
89
- )
90
- })}
91
- </StackWrap>
92
- )
93
- }
80
+ // Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
81
+ // "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
82
+ return (
83
+ <ButtonBase
84
+ ref={itemRef}
85
+ key={id}
86
+ {...pressHandlers}
87
+ onPress={handlePress}
88
+ tokens={getButtonTokens}
89
+ selected={isSelected}
90
+ inactive={inactive}
91
+ {...itemA11y}
92
+ >
93
+ {label}
94
+ </ButtonBase>
95
+ )
96
+ })}
97
+ </StackWrap>
98
+ )
99
+ }
100
+ )
101
+ ButtonGroup.displayName = 'ButtonGroup'
94
102
 
95
103
  ButtonGroup.propTypes = {
96
104
  ...a11yProps.propTypes,
@@ -122,7 +130,11 @@ ButtonGroup.propTypes = {
122
130
  * which will be used in code and passed to any onChange function.
123
131
  * If not provided, the label is used.
124
132
  */
125
- id: PropTypes.string
133
+ id: PropTypes.string,
134
+ /**
135
+ * An optional ref for one individual button in the ButtonGroup
136
+ */
137
+ ref: ABBPropTypes.ref()
126
138
  })
127
139
  ),
128
140
  /**
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import ButtonBase from './ButtonBase'
3
3
  import buttonPropTypes, { textAndA11yText } from './propTypes'
4
4
  import { a11yProps, hrefAttrsProp, linkProps } from '../utils/propTypes'
@@ -8,18 +8,23 @@ import { useThemeTokensCallback } from '../ThemeProvider'
8
8
  * `ButtonLink` is a component with the semantics and behaviour of a link, but with the visual appearance of a button.
9
9
  * ButtonLink is a block-level component and should not be used inline.
10
10
  */
11
- const ButtonLink = ({ accessibilityRole = 'link', tokens, variant, ...props }) => {
12
- const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
13
- const getTokens = useThemeTokensCallback('Button', tokens, variant)
14
- return (
15
- <ButtonBase
16
- accessibilityRole={accessibilityRole}
17
- tokens={getTokens}
18
- hrefAttrs={hrefAttrs}
19
- {...rest}
20
- />
21
- )
22
- }
11
+ const ButtonLink = forwardRef(
12
+ ({ accessibilityRole = 'link', tokens, variant, dataSet, ...props }, ref) => {
13
+ const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
14
+ const getTokens = useThemeTokensCallback('Button', tokens, variant)
15
+ return (
16
+ <ButtonBase
17
+ ref={ref}
18
+ accessibilityRole={accessibilityRole}
19
+ tokens={getTokens}
20
+ hrefAttrs={hrefAttrs}
21
+ dataSet={dataSet}
22
+ {...rest}
23
+ />
24
+ )
25
+ }
26
+ )
27
+ ButtonLink.displayName = 'ButtonLink'
23
28
 
24
29
  ButtonLink.propTypes = {
25
30
  ...a11yProps.types,
package/src/Card/Card.jsx CHANGED
@@ -55,11 +55,11 @@ import CardBase from './CardBase'
55
55
  * you automatically make inaccessible its children, which may or may not be appropriate
56
56
  * depending on what you are trying to achieve.
57
57
  */
58
- const Card = ({ children, tokens, variant, ...rest }) => {
58
+ const Card = ({ children, tokens, variant, dataSet, ...rest }) => {
59
59
  const viewport = useViewport()
60
60
  const themeTokens = useThemeTokens('Card', tokens, variant, { viewport })
61
61
  return (
62
- <CardBase tokens={themeTokens} {...rest}>
62
+ <CardBase tokens={themeTokens} dataSet={dataSet} {...rest}>
63
63
  {children}
64
64
  </CardBase>
65
65
  )
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { View } from 'react-native'
4
4
 
@@ -37,16 +37,17 @@ const selectStyles = ({
37
37
  * A themeless base component for Card which components can apply theme tokens to. Not
38
38
  * intended to be used in apps or sites directly: build themed components on top of this.
39
39
  */
40
- const CardBase = ({ children, tokens, ...rest }) => {
40
+ const CardBase = forwardRef(({ children, tokens, dataSet, ...rest }, ref) => {
41
41
  const cardStyle = selectStyles(typeof tokens === 'function' ? tokens() : tokens)
42
42
  const props = { ...a11yProps.select(rest), ...viewProps.select(rest) }
43
43
 
44
44
  return (
45
- <View style={cardStyle} {...props}>
45
+ <View style={cardStyle} dataSet={dataSet} ref={ref} {...props}>
46
46
  {children}
47
47
  </View>
48
48
  )
49
- }
49
+ })
50
+ CardBase.displayName = 'CardBase'
50
51
 
51
52
  CardBase.propTypes = {
52
53
  children: PropTypes.node,
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Pressable, Platform } from 'react-native'
4
4
 
@@ -33,74 +33,81 @@ export const selectPressableCardTokens = (tokens) =>
33
33
  * based on these to an outer border and a base Card component. Not intended to be used in
34
34
  * apps or sites directly: build themed components on top of this.
35
35
  */
36
- const PressableCardBase = ({
37
- children,
38
- tokens,
39
- checked,
40
- validation,
41
- inactive,
42
- href,
43
- hrefAttrs,
44
- onPress,
45
- accessibilityRole = href ? 'link' : undefined,
46
- ...rest
47
- }) => {
48
- const viewport = useViewport()
49
- const a11y = a11yProps.select({
50
- ...rest,
51
- accessibilityRole
52
- })
53
- const additionalState = { checked, validation, inactive, viewport }
36
+ const PressableCardBase = forwardRef(
37
+ (
38
+ {
39
+ children,
40
+ tokens,
41
+ checked,
42
+ validation,
43
+ inactive,
44
+ href,
45
+ hrefAttrs,
46
+ onPress,
47
+ accessibilityRole = href ? 'link' : undefined,
48
+ ...rest
49
+ },
50
+ ref
51
+ ) => {
52
+ const viewport = useViewport()
53
+ const a11y = a11yProps.select({
54
+ ...rest,
55
+ accessibilityRole
56
+ })
57
+ const additionalState = { checked, validation, inactive, viewport }
54
58
 
55
- const getCardState = (pressableState) => resolvePressableState(pressableState, additionalState)
56
- const getTokens = (pressableState) =>
57
- validateThemeTokens(
58
- resolvePressableTokens(tokens, pressableState, additionalState),
59
- getTokensSetPropType(tokenKeys, { requireAll: true }),
60
- 'PressableCard'
61
- )
59
+ const getCardState = (pressableState) => resolvePressableState(pressableState, additionalState)
60
+ const getTokens = (pressableState) =>
61
+ validateThemeTokens(
62
+ resolvePressableTokens(tokens, pressableState, additionalState),
63
+ getTokensSetPropType(tokenKeys, { requireAll: true }),
64
+ 'PressableCard'
65
+ )
62
66
 
63
- const getCardTokens = (pressableState) => selectTokens('Card', getTokens(pressableState))
64
- const getOuterBorderStyle = (pressableState) => {
65
- const {
66
- flex,
67
- minWidth,
68
- outerBorderColor,
69
- outerBorderGap = 0,
70
- outerBorderWidth = 0,
71
- borderRadius
72
- } = getTokens(pressableState)
73
- return {
74
- flex,
75
- minWidth: minWidth + outerBorderGap + outerBorderWidth,
76
- ...applyOuterBorder({ outerBorderColor, outerBorderGap, outerBorderWidth, borderRadius }),
77
- ...Platform.select({ web: { outline: 'none' } })
67
+ const getCardTokens = (pressableState) => selectTokens('Card', getTokens(pressableState))
68
+ const getOuterBorderStyle = (pressableState) => {
69
+ const {
70
+ flex,
71
+ minWidth,
72
+ outerBorderColor,
73
+ outerBorderGap = 0,
74
+ outerBorderWidth = 0,
75
+ borderRadius
76
+ } = getTokens(pressableState)
77
+ return {
78
+ flex,
79
+ minWidth: minWidth + outerBorderGap + outerBorderWidth,
80
+ ...applyOuterBorder({ outerBorderColor, outerBorderGap, outerBorderWidth, borderRadius }),
81
+ ...Platform.select({ web: { outline: 'none' } })
82
+ }
78
83
  }
79
- }
80
84
 
81
- const handleChange = linkProps.handleHref({ href, onPress })
82
- const handleKeyDown = (e) => {
83
- // The expected keyboard shortcut for selecting a focused item is the Space key
84
- if (e?.key === ' ') handleChange()
85
- }
85
+ const handleChange = linkProps.handleHref({ href, onPress })
86
+ const handleKeyDown = (event) => {
87
+ // The expected keyboard shortcut for selecting a focused item is the Space key
88
+ if (event?.key === ' ') handleChange(event)
89
+ }
86
90
 
87
- return (
88
- <Pressable
89
- href={href}
90
- onPress={handleChange}
91
- onKeyDown={handleKeyDown}
92
- hrefAttrs={hrefAttrs}
93
- style={getOuterBorderStyle}
94
- {...a11y}
95
- >
96
- {(pressableState) => (
97
- <CardBase tokens={getCardTokens(pressableState)}>
98
- {typeof children === 'function' ? children(getCardState(pressableState)) : children}
99
- </CardBase>
100
- )}
101
- </Pressable>
102
- )
103
- }
91
+ return (
92
+ <Pressable
93
+ ref={ref}
94
+ href={href}
95
+ onPress={handleChange}
96
+ onKeyDown={handleKeyDown}
97
+ hrefAttrs={hrefAttrs}
98
+ style={getOuterBorderStyle}
99
+ {...a11y}
100
+ >
101
+ {(pressableState) => (
102
+ <CardBase tokens={getCardTokens(pressableState)}>
103
+ {typeof children === 'function' ? children(getCardState(pressableState)) : children}
104
+ </CardBase>
105
+ )}
106
+ </Pressable>
107
+ )
108
+ }
109
+ )
110
+ PressableCardBase.displayName = 'PressableCardBase'
104
111
 
105
112
  PressableCardBase.propTypes = {
106
113
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),