@telus-uds/components-base 1.8.1 → 1.8.4

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 (288) hide show
  1. package/CHANGELOG.md +35 -2
  2. package/component-docs.json +711 -669
  3. package/lib/A11yInfoProvider/index.js +4 -3
  4. package/lib/A11yText/index.js +6 -5
  5. package/lib/ActivityIndicator/Spinner.js +14 -13
  6. package/lib/ActivityIndicator/Spinner.native.js +10 -8
  7. package/lib/ActivityIndicator/index.js +6 -5
  8. package/lib/ActivityIndicator/shared.js +1 -1
  9. package/lib/BaseProvider/index.js +13 -10
  10. package/lib/Box/Box.js +20 -19
  11. package/lib/Button/Button.js +7 -6
  12. package/lib/Button/ButtonBase.js +97 -79
  13. package/lib/Button/ButtonGroup.js +34 -32
  14. package/lib/Button/ButtonLink.js +9 -7
  15. package/lib/Button/index.js +4 -4
  16. package/lib/Button/propTypes.js +1 -1
  17. package/lib/Card/Card.js +8 -7
  18. package/lib/Card/CardBase.js +35 -31
  19. package/lib/Card/PressableCardBase.js +14 -12
  20. package/lib/Checkbox/Checkbox.js +97 -83
  21. package/lib/Checkbox/CheckboxGroup.js +29 -27
  22. package/lib/Checkbox/CheckboxInput.js +12 -10
  23. package/lib/Divider/Divider.js +10 -9
  24. package/lib/ExpandCollapse/Control.js +42 -36
  25. package/lib/ExpandCollapse/ExpandCollapse.js +11 -10
  26. package/lib/ExpandCollapse/Panel.js +29 -40
  27. package/lib/Feedback/Feedback.js +48 -35
  28. package/lib/Fieldset/Fieldset.js +16 -15
  29. package/lib/Fieldset/FieldsetContainer.js +16 -13
  30. package/lib/Fieldset/FieldsetContainer.native.js +11 -8
  31. package/lib/Fieldset/Legend.js +10 -7
  32. package/lib/Fieldset/Legend.native.js +10 -7
  33. package/lib/FlexGrid/Col/Col.js +18 -17
  34. package/lib/FlexGrid/FlexGrid.js +15 -14
  35. package/lib/FlexGrid/Row/Row.js +13 -12
  36. package/lib/HorizontalScroll/HorizontalScroll.js +25 -20
  37. package/lib/HorizontalScroll/HorizontalScrollButton.js +18 -14
  38. package/lib/HorizontalScroll/ScrollViewEnd.js +6 -5
  39. package/lib/HorizontalScroll/ScrollViewEnd.native.js +12 -9
  40. package/lib/HorizontalScroll/itemPositions.js +19 -13
  41. package/lib/Icon/Icon.js +11 -10
  42. package/lib/Icon/IconText.js +8 -7
  43. package/lib/Icon/index.js +5 -5
  44. package/lib/IconButton/IconButton.js +50 -42
  45. package/lib/InputLabel/InputLabel.js +37 -30
  46. package/lib/InputLabel/LabelContent.js +12 -9
  47. package/lib/InputLabel/LabelContent.native.js +9 -6
  48. package/lib/InputSupports/InputSupports.js +11 -10
  49. package/lib/InputSupports/useInputSupports.js +7 -6
  50. package/lib/Link/ChevronLink.js +9 -8
  51. package/lib/Link/InlinePressable.js +13 -10
  52. package/lib/Link/InlinePressable.native.js +20 -16
  53. package/lib/Link/Link.js +10 -9
  54. package/lib/Link/LinkBase.js +96 -78
  55. package/lib/Link/TextButton.js +9 -8
  56. package/lib/List/List.js +20 -13
  57. package/lib/List/ListItem.js +103 -79
  58. package/lib/Modal/Modal.js +74 -60
  59. package/lib/Notification/Notification.js +46 -33
  60. package/lib/Pagination/PageButton.js +13 -12
  61. package/lib/Pagination/Pagination.js +43 -30
  62. package/lib/Pagination/SideButton.js +21 -18
  63. package/lib/Pagination/usePagination.js +7 -6
  64. package/lib/Progress/Progress.js +23 -19
  65. package/lib/Progress/ProgressBar.js +25 -21
  66. package/lib/Progress/ProgressBarBackground.js +7 -6
  67. package/lib/Radio/Radio.js +80 -69
  68. package/lib/Radio/RadioButton.js +63 -53
  69. package/lib/Radio/RadioGroup.js +30 -28
  70. package/lib/Radio/RadioInput.js +12 -10
  71. package/lib/RadioCard/RadioCard.js +16 -15
  72. package/lib/RadioCard/RadioCardGroup.js +30 -28
  73. package/lib/Search/Search.js +52 -32
  74. package/lib/Select/Group.js +5 -4
  75. package/lib/Select/Group.native.js +4 -3
  76. package/lib/Select/Item.js +10 -7
  77. package/lib/Select/Item.native.js +1 -9
  78. package/lib/Select/Picker.js +16 -15
  79. package/lib/Select/Picker.native.js +49 -38
  80. package/lib/Select/Select.js +134 -113
  81. package/lib/SideNav/Item.js +39 -33
  82. package/lib/SideNav/ItemContent.js +15 -12
  83. package/lib/SideNav/ItemsGroup.js +13 -11
  84. package/lib/SideNav/SideNav.js +21 -18
  85. package/lib/Skeleton/Skeleton.js +60 -44
  86. package/lib/Skeleton/skeleton.constant.js +1 -1
  87. package/lib/Skeleton/skeletonWebAnimation.js +1 -1
  88. package/lib/Spacer/Spacer.js +6 -5
  89. package/lib/StackView/StackView.js +12 -11
  90. package/lib/StackView/StackWrap.js +5 -3
  91. package/lib/StackView/StackWrapBox.js +12 -11
  92. package/lib/StackView/StackWrapGap.js +11 -10
  93. package/lib/StackView/common.js +14 -11
  94. package/lib/StackView/getStackedContent.js +10 -9
  95. package/lib/StackView/index.js +1 -1
  96. package/lib/StepTracker/Step.js +122 -103
  97. package/lib/StepTracker/StepTracker.js +48 -38
  98. package/lib/Tabs/Tabs.js +57 -27
  99. package/lib/Tabs/TabsItem.js +78 -68
  100. package/lib/Tags/Tags.js +68 -62
  101. package/lib/TextInput/TextArea.js +26 -20
  102. package/lib/TextInput/TextInput.js +20 -15
  103. package/lib/TextInput/TextInputBase.js +74 -62
  104. package/lib/TextInput/index.js +4 -4
  105. package/lib/ThemeProvider/ThemeProvider.js +6 -5
  106. package/lib/ThemeProvider/index.js +5 -5
  107. package/lib/ThemeProvider/useSetTheme.js +6 -3
  108. package/lib/ThemeProvider/useThemeTokens.js +7 -2
  109. package/lib/ThemeProvider/utils/styles.js +50 -43
  110. package/lib/ThemeProvider/utils/theme-tokens.js +33 -21
  111. package/lib/ToggleSwitch/ToggleSwitch.js +90 -74
  112. package/lib/ToggleSwitch/ToggleSwitchGroup.js +37 -35
  113. package/lib/Tooltip/Backdrop.js +6 -13
  114. package/lib/Tooltip/Backdrop.native.js +5 -4
  115. package/lib/Tooltip/Tooltip.js +81 -65
  116. package/lib/Tooltip/getTooltipPosition.js +29 -18
  117. package/lib/TooltipButton/TooltipButton.js +28 -21
  118. package/lib/Typography/Typography.js +37 -33
  119. package/lib/ViewportProvider/ViewportProvider.js +4 -3
  120. package/lib/ViewportProvider/useViewportListener.js +6 -3
  121. package/lib/index.js +54 -54
  122. package/lib/utils/a11y/semantics.js +5 -2
  123. package/lib/utils/a11y/textSize.js +8 -6
  124. package/lib/utils/animation/useVerticalExpandAnimation.js +46 -19
  125. package/lib/utils/children.js +4 -3
  126. package/lib/utils/index.js +10 -10
  127. package/lib/utils/input.js +28 -29
  128. package/lib/utils/pressability.js +36 -22
  129. package/lib/utils/props/clickProps.js +2 -1
  130. package/lib/utils/props/componentPropType.js +3 -3
  131. package/lib/utils/props/getPropSelector.js +6 -3
  132. package/lib/utils/props/handlerProps.js +25 -19
  133. package/lib/utils/props/hrefAttrsProp.js +14 -11
  134. package/lib/utils/props/index.js +12 -12
  135. package/lib/utils/props/inputSupportsProps.js +15 -12
  136. package/lib/utils/props/linkProps.js +7 -6
  137. package/lib/utils/props/pressProps.js +1 -1
  138. package/lib/utils/props/selectSystemProps.js +2 -2
  139. package/lib/utils/props/tokens.js +29 -15
  140. package/lib/utils/ssr.js +6 -2
  141. package/lib/utils/useCopy.js +6 -4
  142. package/lib/utils/useHash.js +2 -1
  143. package/lib/utils/useResponsiveProp.js +1 -1
  144. package/lib/utils/useSpacingScale.js +3 -1
  145. package/lib/utils/useUniqueId.js +3 -2
  146. package/lib/utils/withLinkRouter.js +6 -5
  147. package/lib-module/A11yInfoProvider/index.js +4 -3
  148. package/lib-module/A11yText/index.js +6 -5
  149. package/lib-module/ActivityIndicator/Spinner.js +14 -13
  150. package/lib-module/ActivityIndicator/Spinner.native.js +9 -8
  151. package/lib-module/ActivityIndicator/index.js +6 -5
  152. package/lib-module/BaseProvider/index.js +13 -10
  153. package/lib-module/Box/Box.js +20 -19
  154. package/lib-module/Button/Button.js +7 -6
  155. package/lib-module/Button/ButtonBase.js +96 -79
  156. package/lib-module/Button/ButtonGroup.js +34 -32
  157. package/lib-module/Button/ButtonLink.js +8 -7
  158. package/lib-module/Card/Card.js +8 -7
  159. package/lib-module/Card/CardBase.js +35 -31
  160. package/lib-module/Card/PressableCardBase.js +12 -11
  161. package/lib-module/Checkbox/Checkbox.js +97 -83
  162. package/lib-module/Checkbox/CheckboxGroup.js +29 -27
  163. package/lib-module/Checkbox/CheckboxInput.js +12 -10
  164. package/lib-module/Divider/Divider.js +10 -9
  165. package/lib-module/ExpandCollapse/Control.js +42 -36
  166. package/lib-module/ExpandCollapse/ExpandCollapse.js +11 -10
  167. package/lib-module/ExpandCollapse/Panel.js +29 -37
  168. package/lib-module/Feedback/Feedback.js +46 -33
  169. package/lib-module/Fieldset/Fieldset.js +16 -15
  170. package/lib-module/Fieldset/FieldsetContainer.js +16 -13
  171. package/lib-module/Fieldset/FieldsetContainer.native.js +11 -8
  172. package/lib-module/Fieldset/Legend.js +10 -7
  173. package/lib-module/Fieldset/Legend.native.js +10 -7
  174. package/lib-module/FlexGrid/Col/Col.js +18 -17
  175. package/lib-module/FlexGrid/FlexGrid.js +15 -14
  176. package/lib-module/FlexGrid/Row/Row.js +13 -12
  177. package/lib-module/HorizontalScroll/HorizontalScroll.js +24 -19
  178. package/lib-module/HorizontalScroll/HorizontalScrollButton.js +18 -14
  179. package/lib-module/HorizontalScroll/ScrollViewEnd.js +6 -5
  180. package/lib-module/HorizontalScroll/ScrollViewEnd.native.js +12 -9
  181. package/lib-module/HorizontalScroll/itemPositions.js +18 -12
  182. package/lib-module/Icon/Icon.js +10 -9
  183. package/lib-module/Icon/IconText.js +9 -7
  184. package/lib-module/IconButton/IconButton.js +48 -41
  185. package/lib-module/InputLabel/InputLabel.js +37 -30
  186. package/lib-module/InputLabel/LabelContent.js +12 -9
  187. package/lib-module/InputLabel/LabelContent.native.js +9 -6
  188. package/lib-module/InputSupports/InputSupports.js +11 -10
  189. package/lib-module/InputSupports/useInputSupports.js +7 -6
  190. package/lib-module/Link/ChevronLink.js +9 -8
  191. package/lib-module/Link/InlinePressable.js +13 -10
  192. package/lib-module/Link/InlinePressable.native.js +20 -16
  193. package/lib-module/Link/Link.js +10 -9
  194. package/lib-module/Link/LinkBase.js +94 -77
  195. package/lib-module/Link/TextButton.js +9 -8
  196. package/lib-module/List/List.js +20 -13
  197. package/lib-module/List/ListItem.js +103 -78
  198. package/lib-module/Modal/Modal.js +74 -60
  199. package/lib-module/Notification/Notification.js +46 -33
  200. package/lib-module/Pagination/PageButton.js +13 -12
  201. package/lib-module/Pagination/Pagination.js +43 -30
  202. package/lib-module/Pagination/SideButton.js +21 -18
  203. package/lib-module/Pagination/usePagination.js +7 -6
  204. package/lib-module/Progress/Progress.js +23 -19
  205. package/lib-module/Progress/ProgressBar.js +25 -21
  206. package/lib-module/Progress/ProgressBarBackground.js +7 -6
  207. package/lib-module/Radio/Radio.js +80 -69
  208. package/lib-module/Radio/RadioButton.js +62 -52
  209. package/lib-module/Radio/RadioGroup.js +30 -28
  210. package/lib-module/Radio/RadioInput.js +12 -10
  211. package/lib-module/RadioCard/RadioCard.js +16 -15
  212. package/lib-module/RadioCard/RadioCardGroup.js +30 -28
  213. package/lib-module/Search/Search.js +52 -32
  214. package/lib-module/Select/Group.js +5 -4
  215. package/lib-module/Select/Group.native.js +4 -3
  216. package/lib-module/Select/Item.js +10 -7
  217. package/lib-module/Select/Item.native.js +1 -7
  218. package/lib-module/Select/Picker.js +16 -15
  219. package/lib-module/Select/Picker.native.js +46 -36
  220. package/lib-module/Select/Select.js +134 -113
  221. package/lib-module/SideNav/Item.js +39 -33
  222. package/lib-module/SideNav/ItemContent.js +14 -11
  223. package/lib-module/SideNav/ItemsGroup.js +13 -11
  224. package/lib-module/SideNav/SideNav.js +21 -18
  225. package/lib-module/Skeleton/Skeleton.js +60 -44
  226. package/lib-module/Skeleton/skeletonWebAnimation.js +1 -1
  227. package/lib-module/Spacer/Spacer.js +6 -5
  228. package/lib-module/StackView/StackView.js +12 -11
  229. package/lib-module/StackView/StackWrap.js +5 -3
  230. package/lib-module/StackView/StackWrapBox.js +12 -11
  231. package/lib-module/StackView/StackWrapGap.js +11 -10
  232. package/lib-module/StackView/common.js +14 -11
  233. package/lib-module/StackView/getStackedContent.js +10 -9
  234. package/lib-module/StepTracker/Step.js +122 -103
  235. package/lib-module/StepTracker/StepTracker.js +48 -38
  236. package/lib-module/Tabs/Tabs.js +57 -27
  237. package/lib-module/Tabs/TabsItem.js +77 -68
  238. package/lib-module/Tags/Tags.js +68 -62
  239. package/lib-module/TextInput/TextArea.js +26 -20
  240. package/lib-module/TextInput/TextInput.js +19 -15
  241. package/lib-module/TextInput/TextInputBase.js +74 -62
  242. package/lib-module/ThemeProvider/ThemeProvider.js +5 -4
  243. package/lib-module/ThemeProvider/useSetTheme.js +6 -3
  244. package/lib-module/ThemeProvider/useThemeTokens.js +7 -2
  245. package/lib-module/ThemeProvider/utils/styles.js +48 -41
  246. package/lib-module/ThemeProvider/utils/theme-tokens.js +32 -20
  247. package/lib-module/ToggleSwitch/ToggleSwitch.js +90 -74
  248. package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +37 -35
  249. package/lib-module/Tooltip/Backdrop.js +6 -13
  250. package/lib-module/Tooltip/Backdrop.native.js +5 -4
  251. package/lib-module/Tooltip/Tooltip.js +81 -65
  252. package/lib-module/Tooltip/getTooltipPosition.js +29 -18
  253. package/lib-module/TooltipButton/TooltipButton.js +28 -21
  254. package/lib-module/Typography/Typography.js +35 -31
  255. package/lib-module/ViewportProvider/ViewportProvider.js +4 -3
  256. package/lib-module/ViewportProvider/useViewportListener.js +6 -3
  257. package/lib-module/utils/a11y/semantics.js +4 -1
  258. package/lib-module/utils/a11y/textSize.js +7 -5
  259. package/lib-module/utils/animation/useVerticalExpandAnimation.js +47 -20
  260. package/lib-module/utils/children.js +4 -3
  261. package/lib-module/utils/input.js +28 -29
  262. package/lib-module/utils/pressability.js +35 -21
  263. package/lib-module/utils/props/clickProps.js +2 -1
  264. package/lib-module/utils/props/componentPropType.js +3 -3
  265. package/lib-module/utils/props/getPropSelector.js +6 -3
  266. package/lib-module/utils/props/handlerProps.js +24 -18
  267. package/lib-module/utils/props/hrefAttrsProp.js +14 -11
  268. package/lib-module/utils/props/inputSupportsProps.js +15 -12
  269. package/lib-module/utils/props/linkProps.js +7 -6
  270. package/lib-module/utils/props/selectSystemProps.js +2 -2
  271. package/lib-module/utils/props/tokens.js +27 -14
  272. package/lib-module/utils/ssr.js +5 -2
  273. package/lib-module/utils/useCopy.js +6 -4
  274. package/lib-module/utils/useHash.js +2 -1
  275. package/lib-module/utils/useSpacingScale.js +3 -1
  276. package/lib-module/utils/useUniqueId.js +3 -2
  277. package/lib-module/utils/withLinkRouter.js +6 -5
  278. package/package.json +13 -11
  279. package/src/ExpandCollapse/Panel.jsx +2 -19
  280. package/src/List/List.jsx +34 -19
  281. package/src/List/ListItem.jsx +12 -2
  282. package/src/Modal/Modal.jsx +2 -1
  283. package/src/Pagination/Pagination.jsx +3 -0
  284. package/src/Search/Search.jsx +11 -0
  285. package/src/Select/Item.native.jsx +0 -7
  286. package/src/Tabs/Tabs.jsx +24 -2
  287. package/src/Tabs/TabsItem.jsx +6 -5
  288. package/src/utils/animation/useVerticalExpandAnimation.js +47 -13
@@ -1,5 +1,5 @@
1
1
  import React, { forwardRef, useState } from 'react'
2
- import { Animated, Platform, StyleSheet, View } from 'react-native'
2
+ import { Animated, Platform, View } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
 
5
5
  import ExpandCollapseControl from './Control'
@@ -86,13 +86,6 @@ const ExpandCollapsePanel = forwardRef(
86
86
  tokens: themeTokens
87
87
  })
88
88
 
89
- // on web we can hide the contents until we have the container measured and avoid occasional jitter
90
- // this won't work on native platforms
91
- const overflowContainerStyles =
92
- containerHeight === null && Platform.OS === 'web'
93
- ? { height: 0, visibility: 'hidden' }
94
- : undefined
95
-
96
89
  const focusabilityProps = isExpanded ? {} : a11yProps.nonFocusableProps
97
90
 
98
91
  return (
@@ -105,11 +98,7 @@ const ExpandCollapsePanel = forwardRef(
105
98
  >
106
99
  {control}
107
100
  </ExpandCollapseControl>
108
- <Animated.View
109
- ref={animatedRef}
110
- style={[overflowContainerStyles, animatedStyles, staticStyles.itemsContainer]}
111
- {...focusabilityProps}
112
- >
101
+ <Animated.View ref={animatedRef} style={animatedStyles} {...focusabilityProps}>
113
102
  <View onLayout={onContainerLayout}>
114
103
  <View style={selectContainerStyles(themeTokens)}>{children}</View>
115
104
  </View>
@@ -156,10 +145,4 @@ ExpandCollapsePanel.propTypes = {
156
145
  controlTokens: getTokensPropType('ExpandCollapseControl')
157
146
  }
158
147
 
159
- const staticStyles = StyleSheet.create({
160
- itemsContainer: {
161
- overflow: 'hidden'
162
- }
163
- })
164
-
165
148
  export default ExpandCollapsePanel
package/src/List/List.jsx CHANGED
@@ -17,26 +17,41 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
17
17
  * An unordered List component has a child a ListItem that
18
18
  * allows icon, dividers and customized typography
19
19
  */
20
- const List = forwardRef(({ children, showDivider, tokens, variant, ...rest }, ref) => {
21
- const accessibilityRole = Platform.select({ web: 'list', default: 'none' })
22
- const items = Children.map(children, (child, index) => {
23
- if (child.type.name === ListItem.name) {
24
- return cloneElement(child, {
25
- showDivider,
26
- isLastItem: index + 1 === Children.count(children),
27
- tokens,
28
- variant
29
- })
30
- }
31
- return child
32
- })
20
+ const List = forwardRef(
21
+ (
22
+ {
23
+ children,
24
+ showDivider,
25
+ tokens,
26
+ variant,
27
+ accessibilityRole = Platform.select({ web: 'list', default: undefined }),
28
+ ...rest
29
+ },
30
+ ref
31
+ ) => {
32
+ const items = Children.map(children, (child, index) => {
33
+ // Pass ListItem-specific props to children (by name so teams can add their own ListItems)
34
+ const isListItem = (componentName) => Boolean(componentName === ListItem.displayName)
33
35
 
34
- return (
35
- <View ref={ref} accessibilityRole={accessibilityRole} {...selectProps(rest)}>
36
- {items}
37
- </View>
38
- )
39
- })
36
+ if (isListItem(child?.type?.displayName) || isListItem(child?.type?.name)) {
37
+ return cloneElement(child, {
38
+ showDivider,
39
+ isLastItem: index + 1 === Children.count(children),
40
+ tokens,
41
+ variant,
42
+ ...child.props
43
+ })
44
+ }
45
+ return child
46
+ })
47
+
48
+ return (
49
+ <View ref={ref} accessibilityRole={accessibilityRole} {...selectProps(rest)}>
50
+ {items}
51
+ </View>
52
+ )
53
+ }
54
+ )
40
55
  List.displayName = 'List'
41
56
 
42
57
  List.propTypes = {
@@ -65,7 +65,18 @@ const selectDividerStyles = ({ dividerColor, dividerSize, interItemMarginWithDiv
65
65
  */
66
66
  const ListItem = forwardRef(
67
67
  (
68
- { tokens, variant, icon, iconColor, iconSize, showDivider, children, isLastItem, ...rest },
68
+ {
69
+ tokens,
70
+ variant,
71
+ icon,
72
+ iconColor,
73
+ iconSize,
74
+ showDivider,
75
+ children,
76
+ isLastItem,
77
+ accessibilityRole = Platform.select({ web: 'listitem', default: undefined }),
78
+ ...rest
79
+ },
69
80
  ref
70
81
  ) => {
71
82
  const themeTokens = useThemeTokens('List', tokens, variant)
@@ -78,7 +89,6 @@ const ListItem = forwardRef(
78
89
  const itemBulletPositioningStyles = selectBulletPositioningStyles(themeTokens)
79
90
  const iconTokens = selectItemIconTokens(themeTokens)
80
91
  const sideItemContainerStyles = selectSideItemContainerStyles(themeTokens)
81
- const accessibilityRole = Platform.select({ web: 'listitem', default: 'item' })
82
92
 
83
93
  const renderItem = () => (
84
94
  <View style={staticStyles.wrap}>{wrapStringsInText(children, { style: itemStyles })}</View>
@@ -202,6 +202,7 @@ const staticStyles = StyleSheet.create({
202
202
  closeButtonContainer: {
203
203
  position: 'absolute',
204
204
  top: 0,
205
- right: 0
205
+ right: 0,
206
+ zIndex: 1
206
207
  }
207
208
  })
@@ -139,6 +139,9 @@ const Pagination = forwardRef(
139
139
  )
140
140
  }
141
141
  )
142
+
143
+ Pagination.displayName = 'Pagination'
144
+
142
145
  PageButton.displayName = 'PageButton'
143
146
 
144
147
  Pagination.PageButton = PageButton
@@ -68,6 +68,7 @@ const Search = forwardRef(
68
68
  onChange,
69
69
  onSubmit,
70
70
  onClear,
71
+ onFocus,
71
72
  accessibilityLabel,
72
73
  copy = 'en',
73
74
  tokens,
@@ -112,6 +113,10 @@ const Search = forwardRef(
112
113
  if (onClear !== undefined) onClear('', event)
113
114
  }
114
115
 
116
+ const handleFocus = (event) => {
117
+ if (onFocus !== undefined) onFocus(event)
118
+ }
119
+
115
120
  const isEmpty = currentValue === ''
116
121
 
117
122
  // Accessibility label should always be present and correctly localised
@@ -140,6 +145,7 @@ const Search = forwardRef(
140
145
  value={currentValue}
141
146
  onChange={setValue}
142
147
  onSubmitEditing={handleSubmit}
148
+ onFocus={handleFocus}
143
149
  accessibilityLabel={a11yLabelText}
144
150
  />
145
151
  <View style={[staticStyles.iconsContainer, selectIconsContainerStyle(themeTokens)]}>
@@ -214,6 +220,11 @@ Search.propTypes = {
214
220
  */
215
221
  onClear: PropTypes.func,
216
222
  /**
223
+ * Triggered when the search input is focused.
224
+ */
225
+ onFocus: PropTypes.func,
226
+ /**
227
+ *
217
228
  * Use to provide an accessible label for the input (visually hidden).
218
229
  */
219
230
  accessibilityLabel: PropTypes.string,
@@ -1,10 +1,3 @@
1
- import PropTypes from 'prop-types'
2
-
3
1
  const Item = () => null
4
2
 
5
3
  export default Item
6
-
7
- Item.propTypes = {
8
- children: PropTypes.string.isRequired,
9
- value: PropTypes.string.isRequired
10
- }
package/src/Tabs/Tabs.jsx CHANGED
@@ -23,9 +23,24 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
23
23
 
24
24
  const { selectHorizontalScrollTokens, useItemPositions } = horizontalScrollUtils
25
25
 
26
+ const getDefaultTabItemAccessibilityRole = (parentRole) => {
27
+ switch (parentRole) {
28
+ case 'tablist':
29
+ return 'tab'
30
+ case 'navigation':
31
+ return 'link'
32
+ default:
33
+ return undefined
34
+ }
35
+ }
36
+
26
37
  /**
27
38
  * Tabs renders a horizontally-scrolling menu of selectable buttons which may link
28
39
  * to a page or control what content is displayed on this page.
40
+ *
41
+ * If you are using Tabs to navigate to a new page (web-only) you should pass
42
+ * `navigation`as the `accessibilityRole` to te Tabs component, this will cause
43
+ * TabItems to default to a role of link and obtain aria-current behaviour.
29
44
  */
30
45
  const Tabs = forwardRef(
31
46
  (
@@ -61,6 +76,11 @@ const Tabs = forwardRef(
61
76
  isPositioningReady
62
77
  )
63
78
 
79
+ const restProps = selectProps(rest)
80
+ const parentAccessibilityRole = restProps.accessibilityRole ?? 'tablist'
81
+ const defaultTabItemAccessibiltyRole =
82
+ getDefaultTabItemAccessibilityRole(parentAccessibilityRole)
83
+
64
84
  return (
65
85
  <HorizontalScroll
66
86
  ref={ref}
@@ -68,8 +88,8 @@ const Tabs = forwardRef(
68
88
  itemPositions={itemPositions}
69
89
  tokens={selectHorizontalScrollTokens(themeTokens)}
70
90
  scrollButtonTokens={scrollButtonTokens}
71
- accessibilityRole="tablist"
72
- {...selectProps(rest)}
91
+ accessibilityRole={parentAccessibilityRole}
92
+ {...restProps}
73
93
  >
74
94
  <StackView space={space} direction="row">
75
95
  {items.map(
@@ -78,6 +98,7 @@ const Tabs = forwardRef(
78
98
  href,
79
99
  label,
80
100
  id,
101
+ accessibilityRole = defaultTabItemAccessibiltyRole,
81
102
  ref: itemRef,
82
103
  LinkRouter: ItemLinkRouter = LinkRouter,
83
104
  linkRouterProps: itemLinkRouterProps
@@ -98,6 +119,7 @@ const Tabs = forwardRef(
98
119
  selected={isSelected}
99
120
  itemPositions={itemPositions}
100
121
  index={index}
122
+ accessibilityRole={accessibilityRole}
101
123
  LinkRouter={ItemLinkRouter}
102
124
  linkRouterProps={{ ...linkRouterProps, ...itemLinkRouterProps }}
103
125
  >
@@ -86,11 +86,11 @@ const TabsItem = forwardRef(
86
86
  itemPositions,
87
87
  index,
88
88
  children,
89
- accessibilityRole = href ? 'link' : 'tab',
90
- accessibilityState = Platform.OS === 'web' && accessibilityRole === 'link'
91
- ? // Web links can't be aria-selected but can be aria-current
92
- { current: selected ? 'page' : false }
93
- : { selected },
89
+ accessibilityRole,
90
+ accessibilityCurrent = Platform.OS === 'web' && accessibilityRole === 'link' && selected
91
+ ? 'page'
92
+ : undefined,
93
+ accessibilityState = accessibilityRole === 'tab' ? { selected } : undefined,
94
94
  ...rawRest
95
95
  },
96
96
  ref
@@ -121,6 +121,7 @@ const TabsItem = forwardRef(
121
121
 
122
122
  const selectedProps = selectProps({
123
123
  accessibilityRole,
124
+ accessibilityCurrent,
124
125
  accessibilityState,
125
126
  ...rest
126
127
  })
@@ -1,21 +1,27 @@
1
- import { useEffect, useRef, useState } from 'react'
1
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react'
2
2
  import { Animated, Easing, Platform } from 'react-native'
3
3
 
4
4
  // TODO: systematise animations
5
5
  // https://github.com/telus/universal-design-system/issues/487
6
6
  function useVerticalExpandAnimation({ containerHeight, isExpanded, tokens }) {
7
7
  const [isAnimating, setIsAnimating] = useState(false)
8
+ const [wasExpanded, setWasExpanded] = useState(isExpanded)
9
+ const expandStateChanged = isExpanded !== wasExpanded
8
10
 
9
11
  const expandAnimatedValue = useRef(new Animated.Value(0)).current
10
12
  const elementRef = useRef(null)
11
13
 
12
14
  const { expandDuration, collapseDuration } = tokens
13
15
 
14
- // Treat as animating from when expanded state changes, until animation completes
15
- useEffect(() => setIsAnimating(true), [isExpanded])
16
+ useLayoutEffect(() => {
17
+ if (expandStateChanged) {
18
+ setIsAnimating(true)
19
+ setWasExpanded(isExpanded)
20
+ }
21
+ }, [expandStateChanged, isExpanded])
16
22
 
17
23
  useEffect(() => {
18
- const onComplete = () => !isExpanded && setIsAnimating(false)
24
+ const onComplete = () => setIsAnimating(false)
19
25
 
20
26
  if (Platform.OS === 'web') {
21
27
  if (!elementRef.current) return () => {}
@@ -39,19 +45,47 @@ function useVerticalExpandAnimation({ containerHeight, isExpanded, tokens }) {
39
45
  return () => animation.stop()
40
46
  }, [isExpanded, expandAnimatedValue, containerHeight, expandDuration, collapseDuration])
41
47
 
42
- // Without `visibility: 'hidden', descendents are focusable on web even when collapsed
43
- const containerStyles = !isExpanded && !isAnimating ? { visibility: 'hidden' } : {}
48
+ const containerStyles = {}
44
49
 
45
- // don't visually collapse the container until we have it measured
46
- if (containerHeight !== null) {
47
- if (Platform.OS === 'web') {
48
- const transitionDuration = isExpanded ? expandDuration : collapseDuration
49
- containerStyles.transition = `height ${transitionDuration}ms ease-in-out`
50
+ if (isAnimating || expandStateChanged) containerStyles.overflow = 'hidden'
50
51
 
51
- containerStyles.height = isExpanded ? containerHeight : 0
52
+ if (!isExpanded && !isAnimating && !expandStateChanged) {
53
+ if (Platform.OS === 'web') {
54
+ // Without `visibility: 'hidden', descendents are focusable on web even when collapsed.
55
+ containerStyles.visibility = 'hidden'
52
56
  } else {
53
- containerStyles.height = expandAnimatedValue
57
+ // There's no `visibility: hidden` in React Native, and display: none causes a flicker on expand.
58
+ // Without some form of hiding, some children leak through even when closed e.g. `List.Item` bullets.
59
+ containerStyles.opacity = 0
60
+ }
61
+ }
62
+
63
+ // don't visually collapse the container until we have it measured
64
+ if (containerHeight === null) {
65
+ if (Platform.OS === 'web') {
66
+ // on web we can hide the contents until we have the container measured and avoid occasional jitter
67
+ // this won't work on native platforms
68
+ containerStyles.height = 0
69
+ containerStyles.visibility = 'hidden'
54
70
  }
71
+ } else if (Platform.OS === 'web') {
72
+ const transitionDuration = isExpanded ? expandDuration : collapseDuration
73
+ containerStyles.transition = `height ${transitionDuration}ms ease-in-out`
74
+
75
+ containerStyles.height = isExpanded ? containerHeight : 0
76
+ } else if (
77
+ Platform.OS === 'ios' &&
78
+ isExpanded &&
79
+ !isAnimating &&
80
+ !expandStateChanged &&
81
+ typeof containerHeight === 'number'
82
+ ) {
83
+ // iOS reflows text while the height animation is in progress. Sometimes, it hits a timing bug where
84
+ // it fails to reflow properly after the last animation frame, leaving the last line of text not visible.
85
+ // Force reflow after animation completes with a static height non-identical to the last animated height.
86
+ containerStyles.height = containerHeight + 1
87
+ } else {
88
+ containerStyles.height = expandAnimatedValue
55
89
  }
56
90
 
57
91
  return [containerStyles, elementRef]