@telus-uds/components-base 0.0.2-prerelease.7 → 0.0.2-prerelease.8

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 (349) hide show
  1. package/.ultra.cache.json +1 -1
  2. package/CHANGELOG.md +27 -0
  3. package/__fixtures__/Accessible.js +33 -0
  4. package/__fixtures__/Accessible.native.js +32 -0
  5. package/__fixtures__/testTheme.js +429 -29
  6. package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
  7. package/__tests__/Button/ButtonGroup.test.jsx +2 -2
  8. package/__tests__/Checkbox/CheckboxGroup.test.jsx +247 -0
  9. package/__tests__/Icon/Icon.test.jsx +3 -3
  10. package/__tests__/Modal/Modal.test.jsx +47 -0
  11. package/__tests__/Notification/Notification.test.jsx +20 -0
  12. package/__tests__/Pagination/Pagination.test.jsx +2 -2
  13. package/__tests__/Progress/Progress.test.jsx +79 -0
  14. package/__tests__/Radio/RadioGroup.test.jsx +221 -0
  15. package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
  16. package/__tests__/RadioCard/RadioCardGroup.test.jsx +247 -0
  17. package/__tests__/Search/Search.test.jsx +72 -0
  18. package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
  19. package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
  20. package/__tests__/Tabs/Tabs.test.jsx +200 -0
  21. package/__tests__/Tags/Tags.test.jsx +1 -1
  22. package/__tests__/utils/input.test.js +58 -0
  23. package/__tests__/utils/useCopy.test.js +14 -3
  24. package/babel.config.js +20 -0
  25. package/jest.config.js +1 -1
  26. package/lib/A11yInfoProvider/index.js +54 -26
  27. package/lib/A11yText/index.js +37 -14
  28. package/lib/ActivityIndicator/Spinner.js +78 -0
  29. package/lib/ActivityIndicator/Spinner.native.js +121 -87
  30. package/lib/ActivityIndicator/index.js +28 -12
  31. package/lib/ActivityIndicator/shared.js +27 -12
  32. package/lib/BaseProvider/index.js +34 -11
  33. package/lib/Box/Box.js +54 -31
  34. package/lib/Box/index.js +13 -2
  35. package/lib/Button/Button.js +32 -11
  36. package/lib/Button/ButtonBase.js +85 -78
  37. package/lib/Button/ButtonGroup.js +94 -70
  38. package/lib/Button/ButtonLink.js +38 -15
  39. package/lib/Button/index.js +31 -4
  40. package/lib/Button/propTypes.js +32 -9
  41. package/lib/Card/Card.js +36 -41
  42. package/lib/Card/CardBase.js +78 -0
  43. package/lib/Card/PressableCardBase.js +137 -0
  44. package/lib/Card/index.js +40 -2
  45. package/lib/Checkbox/Checkbox.js +139 -103
  46. package/lib/Checkbox/CheckboxGroup.js +231 -0
  47. package/lib/Checkbox/CheckboxInput.js +74 -0
  48. package/lib/Checkbox/CheckboxInput.native.js +9 -1
  49. package/lib/Checkbox/index.js +21 -2
  50. package/lib/Divider/Divider.js +50 -24
  51. package/lib/Divider/index.js +13 -2
  52. package/lib/ExpandCollapse/Accordion.js +20 -7
  53. package/lib/ExpandCollapse/Control.js +50 -27
  54. package/lib/ExpandCollapse/ExpandCollapse.js +41 -24
  55. package/lib/ExpandCollapse/Panel.js +75 -37
  56. package/lib/ExpandCollapse/index.js +25 -7
  57. package/lib/Feedback/Feedback.js +69 -40
  58. package/lib/Feedback/index.js +13 -2
  59. package/lib/Fieldset/Fieldset.js +160 -0
  60. package/lib/Fieldset/FieldsetContainer.js +41 -0
  61. package/lib/Fieldset/FieldsetContainer.native.js +33 -0
  62. package/lib/Fieldset/Legend.js +33 -0
  63. package/lib/Fieldset/Legend.native.js +43 -0
  64. package/lib/Fieldset/cssReset.js +21 -0
  65. package/lib/Fieldset/index.js +13 -0
  66. package/lib/FlexGrid/Col/Col.js +67 -38
  67. package/lib/FlexGrid/Col/index.js +13 -2
  68. package/lib/FlexGrid/FlexGrid.js +70 -45
  69. package/lib/FlexGrid/Row/Row.js +48 -27
  70. package/lib/FlexGrid/Row/index.js +13 -2
  71. package/lib/FlexGrid/helpers/index.js +9 -1
  72. package/lib/FlexGrid/index.js +13 -2
  73. package/lib/FlexGrid/providers/GutterContext.js +15 -3
  74. package/lib/Icon/Icon.js +46 -44
  75. package/lib/Icon/IconText.js +49 -21
  76. package/lib/Icon/index.js +31 -4
  77. package/lib/InputLabel/InputLabel.js +70 -36
  78. package/lib/InputLabel/LabelContent.js +31 -0
  79. package/lib/InputLabel/LabelContent.native.js +9 -1
  80. package/lib/InputLabel/index.js +13 -2
  81. package/lib/InputSupports/InputSupports.js +62 -48
  82. package/lib/InputSupports/index.js +13 -2
  83. package/lib/InputSupports/propTypes.js +19 -8
  84. package/lib/InputSupports/useInputSupports.js +41 -0
  85. package/lib/Link/ChevronLink.js +33 -16
  86. package/lib/Link/InlinePressable.js +50 -0
  87. package/lib/Link/InlinePressable.native.js +34 -11
  88. package/lib/Link/Link.js +25 -9
  89. package/lib/Link/LinkBase.js +87 -57
  90. package/lib/Link/TextButton.js +32 -13
  91. package/lib/Link/index.js +39 -5
  92. package/lib/List/List.js +51 -23
  93. package/lib/List/ListItem.js +70 -40
  94. package/lib/List/index.js +13 -2
  95. package/lib/Modal/Modal.js +226 -0
  96. package/lib/Modal/dictionary.js +16 -0
  97. package/lib/Modal/index.js +13 -0
  98. package/lib/Notification/Notification.js +200 -0
  99. package/lib/Notification/dictionary.js +15 -0
  100. package/lib/Notification/index.js +13 -0
  101. package/lib/Pagination/PageButton.js +47 -25
  102. package/lib/Pagination/Pagination.js +70 -40
  103. package/lib/Pagination/SideButton.js +63 -37
  104. package/lib/Pagination/dictionary.js +9 -2
  105. package/lib/Pagination/index.js +13 -2
  106. package/lib/Pagination/usePagination.js +12 -2
  107. package/lib/Progress/Progress.js +99 -0
  108. package/lib/Progress/ProgressBar.js +146 -0
  109. package/lib/Progress/ProgressBarBackground.js +57 -0
  110. package/lib/Progress/index.js +16 -0
  111. package/lib/Radio/Radio.js +110 -109
  112. package/lib/Radio/RadioButton.js +141 -0
  113. package/lib/Radio/RadioGroup.js +233 -0
  114. package/lib/Radio/RadioInput.js +76 -0
  115. package/lib/Radio/RadioInput.native.js +9 -1
  116. package/lib/Radio/index.js +21 -2
  117. package/lib/RadioCard/RadioCard.js +240 -0
  118. package/lib/RadioCard/RadioCardGroup.js +251 -0
  119. package/lib/RadioCard/index.js +21 -0
  120. package/lib/Search/Search.js +243 -0
  121. package/lib/Search/dictionary.js +19 -0
  122. package/lib/Search/index.js +13 -0
  123. package/lib/Select/Group.js +33 -0
  124. package/lib/Select/Group.native.js +16 -5
  125. package/lib/Select/Item.js +29 -0
  126. package/lib/Select/Item.native.js +14 -4
  127. package/lib/Select/Picker.js +79 -0
  128. package/lib/Select/Picker.native.js +52 -24
  129. package/lib/Select/Select.js +110 -82
  130. package/lib/Select/index.js +19 -6
  131. package/lib/SideNav/Item.js +54 -33
  132. package/lib/SideNav/ItemContent.js +41 -15
  133. package/lib/SideNav/ItemsGroup.js +46 -27
  134. package/lib/SideNav/SideNav.js +92 -69
  135. package/lib/SideNav/index.js +15 -1
  136. package/lib/Skeleton/Skeleton.js +55 -37
  137. package/lib/Skeleton/index.js +13 -2
  138. package/lib/Skeleton/skeleton.constant.js +12 -0
  139. package/lib/Skeleton/skeletonWebAnimation.js +27 -0
  140. package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
  141. package/lib/Spacer/Spacer.js +31 -12
  142. package/lib/Spacer/index.js +13 -2
  143. package/lib/StackView/StackView.js +49 -27
  144. package/lib/StackView/StackWrap.js +33 -10
  145. package/lib/StackView/StackWrap.native.js +13 -2
  146. package/lib/StackView/StackWrapBox.js +46 -24
  147. package/lib/StackView/StackWrapGap.js +43 -22
  148. package/lib/StackView/common.js +19 -4
  149. package/lib/StackView/getStackedContent.js +49 -19
  150. package/lib/StackView/index.js +29 -5
  151. package/lib/StepTracker/Step.js +245 -0
  152. package/lib/StepTracker/StepTracker.js +197 -0
  153. package/lib/StepTracker/dictionary.js +17 -0
  154. package/lib/StepTracker/index.js +13 -0
  155. package/lib/Tabs/HorizontalScroll.js +199 -0
  156. package/lib/Tabs/ScrollViewEnd.js +66 -0
  157. package/lib/Tabs/ScrollViewEnd.native.js +41 -0
  158. package/lib/Tabs/Tabs.js +117 -0
  159. package/lib/Tabs/TabsItem.js +234 -0
  160. package/lib/Tabs/TabsScrollButton.js +121 -0
  161. package/lib/Tabs/dictionary.js +18 -0
  162. package/lib/Tabs/index.js +13 -0
  163. package/lib/Tabs/itemPositions.js +128 -0
  164. package/lib/Tags/Tags.js +130 -97
  165. package/lib/Tags/index.js +13 -2
  166. package/lib/TextInput/TextArea.js +51 -24
  167. package/lib/TextInput/TextInput.js +40 -19
  168. package/lib/TextInput/TextInputBase.js +78 -55
  169. package/lib/TextInput/index.js +23 -3
  170. package/lib/TextInput/propTypes.js +18 -7
  171. package/lib/ThemeProvider/ThemeProvider.js +38 -14
  172. package/lib/ThemeProvider/index.js +61 -6
  173. package/lib/ThemeProvider/useSetTheme.js +14 -5
  174. package/lib/ThemeProvider/useTheme.js +13 -4
  175. package/lib/ThemeProvider/useThemeTokens.js +32 -16
  176. package/lib/ThemeProvider/utils/index.js +31 -2
  177. package/lib/ThemeProvider/utils/styles.js +52 -16
  178. package/lib/ThemeProvider/utils/theme-tokens.js +94 -16
  179. package/lib/ToggleSwitch/ToggleSwitch.js +75 -51
  180. package/lib/ToggleSwitch/index.js +13 -2
  181. package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +22 -18
  182. package/lib/Tooltip/Backdrop.native.js +39 -15
  183. package/lib/Tooltip/Tooltip.js +112 -70
  184. package/lib/Tooltip/dictionary.js +9 -2
  185. package/lib/Tooltip/getTooltipPosition.js +9 -1
  186. package/lib/Tooltip/index.js +13 -2
  187. package/lib/TooltipButton/TooltipButton.js +57 -38
  188. package/lib/TooltipButton/index.js +13 -2
  189. package/lib/Typography/Typography.js +57 -27
  190. package/lib/Typography/index.js +13 -2
  191. package/lib/ViewportProvider/ViewportProvider.js +34 -13
  192. package/lib/ViewportProvider/index.js +28 -3
  193. package/lib/ViewportProvider/useViewport.js +15 -3
  194. package/lib/ViewportProvider/useViewportListener.js +24 -10
  195. package/lib/index.js +509 -33
  196. package/lib/utils/a11y/index.js +18 -1
  197. package/lib/utils/a11y/textSize.js +23 -7
  198. package/lib/utils/animation/index.js +15 -2
  199. package/lib/utils/animation/useVerticalExpandAnimation.js +28 -11
  200. package/lib/utils/children.js +87 -0
  201. package/lib/utils/index.js +163 -10
  202. package/lib/utils/info/index.js +18 -6
  203. package/lib/utils/info/platform/index.js +19 -7
  204. package/lib/utils/info/platform/platform.android.js +8 -1
  205. package/lib/utils/info/platform/platform.ios.js +8 -1
  206. package/lib/utils/info/platform/platform.js +8 -0
  207. package/lib/utils/info/platform/platform.native.js +8 -1
  208. package/lib/utils/info/versions.js +15 -4
  209. package/lib/utils/input.js +51 -33
  210. package/lib/utils/pressability.js +38 -10
  211. package/lib/utils/propTypes.js +217 -125
  212. package/lib/utils/useCopy.js +40 -5
  213. package/lib/utils/useHash.js +48 -0
  214. package/lib/utils/useHash.native.js +15 -0
  215. package/lib/utils/useResponsiveProp.js +21 -9
  216. package/lib/utils/useSpacingScale.js +21 -9
  217. package/lib/utils/useUniqueId.js +13 -4
  218. package/package.json +7 -6
  219. package/release-context.json +4 -4
  220. package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +0 -0
  221. package/src/Box/Box.jsx +11 -4
  222. package/src/Button/Button.jsx +3 -2
  223. package/src/Button/ButtonBase.jsx +27 -36
  224. package/src/Button/ButtonGroup.jsx +2 -2
  225. package/src/Button/ButtonLink.jsx +3 -2
  226. package/src/Button/propTypes.js +12 -2
  227. package/src/Card/Card.jsx +4 -30
  228. package/src/Card/CardBase.jsx +57 -0
  229. package/src/Card/PressableCardBase.jsx +112 -0
  230. package/src/Card/index.js +3 -0
  231. package/src/Checkbox/Checkbox.jsx +10 -11
  232. package/src/Checkbox/CheckboxGroup.jsx +196 -0
  233. package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
  234. package/src/Checkbox/index.js +2 -0
  235. package/src/ExpandCollapse/Control.jsx +1 -1
  236. package/src/Feedback/Feedback.jsx +1 -1
  237. package/src/Fieldset/Fieldset.jsx +129 -0
  238. package/src/Fieldset/FieldsetContainer.jsx +22 -0
  239. package/src/Fieldset/FieldsetContainer.native.jsx +16 -0
  240. package/src/Fieldset/Legend.jsx +16 -0
  241. package/src/Fieldset/Legend.native.jsx +22 -0
  242. package/src/Fieldset/cssReset.js +14 -0
  243. package/src/Fieldset/index.js +3 -0
  244. package/src/Icon/Icon.jsx +14 -23
  245. package/src/Icon/IconText.jsx +2 -2
  246. package/src/Icon/index.js +2 -2
  247. package/src/InputLabel/InputLabel.jsx +9 -2
  248. package/src/InputLabel/{LabelContent.web.jsx → LabelContent.jsx} +0 -0
  249. package/src/InputSupports/InputSupports.jsx +7 -18
  250. package/src/InputSupports/useInputSupports.js +30 -0
  251. package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +0 -0
  252. package/src/Link/LinkBase.jsx +14 -12
  253. package/src/Modal/Modal.jsx +185 -0
  254. package/src/Modal/dictionary.js +9 -0
  255. package/src/Modal/index.js +3 -0
  256. package/src/Notification/Notification.jsx +149 -0
  257. package/src/Notification/dictionary.js +8 -0
  258. package/src/Notification/index.js +3 -0
  259. package/src/Progress/Progress.jsx +77 -0
  260. package/src/Progress/ProgressBar.jsx +110 -0
  261. package/src/Progress/ProgressBarBackground.jsx +34 -0
  262. package/src/Progress/index.js +6 -0
  263. package/src/Radio/Radio.jsx +19 -56
  264. package/src/Radio/RadioButton.jsx +131 -0
  265. package/src/Radio/RadioGroup.jsx +198 -0
  266. package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
  267. package/src/Radio/index.js +2 -0
  268. package/src/RadioCard/RadioCard.jsx +191 -0
  269. package/src/RadioCard/RadioCardGroup.jsx +211 -0
  270. package/src/RadioCard/index.js +5 -0
  271. package/src/Search/Search.jsx +204 -0
  272. package/src/Search/dictionary.js +12 -0
  273. package/src/Search/index.js +3 -0
  274. package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
  275. package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
  276. package/src/Select/{Picker.web.jsx → Picker.jsx} +0 -0
  277. package/src/Select/Select.jsx +12 -22
  278. package/src/SideNav/Item.jsx +2 -2
  279. package/src/Skeleton/Skeleton.jsx +17 -20
  280. package/src/Skeleton/skeleton.constant.js +3 -0
  281. package/src/Skeleton/skeletonWebAnimation.js +13 -0
  282. package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
  283. package/src/StackView/StackView.jsx +10 -3
  284. package/src/StackView/StackWrap.jsx +9 -1
  285. package/src/StackView/StackWrapBox.jsx +4 -3
  286. package/src/StackView/StackWrapGap.jsx +3 -3
  287. package/src/StackView/getStackedContent.jsx +8 -2
  288. package/src/StepTracker/Step.jsx +202 -0
  289. package/src/StepTracker/StepTracker.jsx +163 -0
  290. package/src/StepTracker/dictionary.js +10 -0
  291. package/src/StepTracker/index.js +3 -0
  292. package/src/Tabs/HorizontalScroll.jsx +165 -0
  293. package/src/Tabs/ScrollViewEnd.jsx +53 -0
  294. package/src/Tabs/ScrollViewEnd.native.jsx +24 -0
  295. package/src/Tabs/Tabs.jsx +89 -0
  296. package/src/Tabs/TabsItem.jsx +204 -0
  297. package/src/Tabs/TabsScrollButton.jsx +100 -0
  298. package/src/Tabs/dictionary.js +11 -0
  299. package/src/Tabs/index.js +3 -0
  300. package/src/Tabs/itemPositions.js +101 -0
  301. package/src/Tags/Tags.jsx +2 -1
  302. package/src/TextInput/TextInputBase.jsx +12 -22
  303. package/src/ThemeProvider/useThemeTokens.js +2 -2
  304. package/src/ThemeProvider/utils/styles.js +18 -5
  305. package/src/ThemeProvider/utils/theme-tokens.js +46 -5
  306. package/src/ToggleSwitch/ToggleSwitch.jsx +2 -3
  307. package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
  308. package/src/Tooltip/Tooltip.jsx +1 -1
  309. package/src/TooltipButton/TooltipButton.jsx +23 -27
  310. package/src/Typography/Typography.jsx +6 -5
  311. package/src/index.js +20 -2
  312. package/src/utils/children.jsx +66 -0
  313. package/src/utils/index.js +3 -0
  314. package/src/utils/info/platform/platform.js +1 -0
  315. package/src/utils/info/versions.js +2 -2
  316. package/src/utils/input.js +20 -12
  317. package/src/utils/pressability.js +4 -0
  318. package/src/utils/propTypes.js +98 -34
  319. package/src/utils/useCopy.js +30 -4
  320. package/src/utils/useHash.js +34 -0
  321. package/src/utils/useHash.native.js +6 -0
  322. package/stories/A11yText/A11yText.stories.jsx +4 -8
  323. package/stories/Checkbox/Checkbox.stories.jsx +24 -1
  324. package/stories/Icon/Icon.stories.jsx +6 -5
  325. package/stories/Modal/Modal.stories.jsx +29 -0
  326. package/stories/Notification/Notification.stories.jsx +82 -0
  327. package/stories/Progress/Progress.stories.jsx +93 -0
  328. package/stories/Radio/Radio.stories.jsx +23 -36
  329. package/stories/RadioCard/RadioCard.stories.jsx +98 -0
  330. package/stories/Search/Search.stories.jsx +16 -0
  331. package/stories/StepTracker/StepTracker.stories.jsx +71 -0
  332. package/stories/Tabs/Tabs.stories.jsx +97 -0
  333. package/stories/{platform-supports.web.jsx → platform-supports.jsx} +0 -0
  334. package/__fixtures__/accessible.icon.svg +0 -6
  335. package/babel.config.json +0 -8
  336. package/lib/ActivityIndicator/Spinner.web.js +0 -55
  337. package/lib/Checkbox/CheckboxInput.web.js +0 -57
  338. package/lib/InputLabel/LabelContent.web.js +0 -17
  339. package/lib/Link/InlinePressable.web.js +0 -32
  340. package/lib/Radio/RadioInput.web.js +0 -59
  341. package/lib/Select/Group.web.js +0 -18
  342. package/lib/Select/Item.web.js +0 -15
  343. package/lib/Select/Picker.web.js +0 -63
  344. package/lib/config/svgr-icons-web.js +0 -9
  345. package/lib/config/svgr-icons.js +0 -52
  346. package/lib/utils/info/platform/platform.web.js +0 -1
  347. package/src/config/svgr-icons-web.js +0 -11
  348. package/src/config/svgr-icons.js +0 -46
  349. package/src/utils/info/platform/platform.web.js +0 -1
package/src/Icon/Icon.jsx CHANGED
@@ -5,13 +5,19 @@ import PropTypes from 'prop-types'
5
5
  import { useThemeTokens } from '../ThemeProvider'
6
6
  import { getTokensPropType, scaleWithText, variantProp } from '../utils'
7
7
 
8
- const Icon = ({ IconSvg, variant, label, titleId, tokens, scalesWithText = false }) => {
8
+ const Icon = ({
9
+ icon: IconComponent,
10
+ accessibilityLabel,
11
+ variant,
12
+ tokens,
13
+ scalesWithText = false
14
+ }) => {
9
15
  const themeTokens = useThemeTokens('Icon', tokens, variant)
10
16
 
11
17
  const size = scalesWithText ? scaleWithText(themeTokens.size) : themeTokens.size
12
18
 
13
19
  const iconContent = (
14
- <IconSvg title={label} titleId={titleId} size={size} color={themeTokens.color} />
20
+ <IconComponent title={accessibilityLabel} size={size} color={themeTokens.color} />
15
21
  )
16
22
 
17
23
  return Platform.OS === 'web' ? (
@@ -37,41 +43,26 @@ const Icon = ({ IconSvg, variant, label, titleId, tokens, scalesWithText = false
37
43
  )
38
44
  }
39
45
 
40
- // Auto-generated SVG icon components wrap Icon and pass through these props:
41
46
  export const iconComponentPropTypes = {
42
47
  variant: variantProp.propType,
43
48
  tokens: getTokensPropType('Icon'),
44
49
  /**
45
50
  * Descriptive label used in web SVG title tag for accessibility
46
51
  */
47
- label: PropTypes.string,
52
+ accessibilityLabel: PropTypes.string,
48
53
  /**
49
- * On web, this unique id is applied to <SVG> title and aria-labelledby attr
54
+ * controls whether the icon size should be proportionate to any accessibility-related font scaling.
50
55
  */
51
- titleId: PropTypes.string
52
- }
53
-
54
- // Auto-generated SVG icon components contain an inner SVG component taking these props:
55
- export const iconSvgPropTypes = {
56
- title: iconComponentPropTypes.label,
57
- titleId: iconComponentPropTypes.titleId,
58
- /**
59
- * The size of the SVG icon after resolving tokens
60
- */
61
- size: PropTypes.number,
62
- /**
63
- * The color of the SVG icon after resolving tokens
64
- */
65
- color: PropTypes.string
56
+ scalesWithText: PropTypes.bool
66
57
  }
67
58
 
68
59
  Icon.propTypes = {
69
60
  ...iconComponentPropTypes,
70
61
  /**
71
- * Function component containing this icon's SVG or native equivalent.
72
- * UDS's SVGR config turns static SVG files into components that pass this to <Icon>.
62
+ * A valid UDS icon component imported from a UDS palette
63
+ * (e.g.) `import { MyIcon } from @telus-uds/palette-<brand>/build/web/icons`
73
64
  */
74
- IconSvg: PropTypes.func.isRequired
65
+ icon: PropTypes.elementType.isRequired
75
66
  }
76
67
 
77
68
  export default Icon
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Platform, View } from 'react-native'
4
4
 
5
- import { iconComponentPropTypes } from './Icon'
5
+ import Icon, { iconComponentPropTypes } from './Icon'
6
6
  import { getStackedContent } from '../StackView'
7
7
  import { spacingProps } from '../utils'
8
8
 
@@ -15,7 +15,7 @@ import { spacingProps } from '../utils'
15
15
  * - within a container with `flexDirection: 'row'`
16
16
  */
17
17
  const IconText = ({ space, iconPosition = 'left', icon: IconComponent, iconProps, children }) => {
18
- const iconContent = IconComponent && <IconComponent scalesWithText {...iconProps} />
18
+ const iconContent = IconComponent && <Icon icon={IconComponent} scalesWithText {...iconProps} />
19
19
 
20
20
  // Inline images on Android are always baseline-aligned which makes them look misaligned - offset it.
21
21
  // See abandoned issue https://github.com/facebook/react-native/issues/6529
package/src/Icon/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import Icon, { iconComponentPropTypes, iconSvgPropTypes } from './Icon'
1
+ import Icon, { iconComponentPropTypes } from './Icon'
2
2
  import IconText from './IconText'
3
3
 
4
4
  export default Icon
5
- export { iconComponentPropTypes, iconSvgPropTypes, IconText }
5
+ export { iconComponentPropTypes, IconText }
@@ -57,7 +57,11 @@ function InputLabel({
57
57
  {hint}
58
58
  </Text>
59
59
  )}
60
- {hasTooltip && <Tooltip content={tooltip} />}
60
+ {hasTooltip && (
61
+ <View style={staticStyles.tooltipAlign}>
62
+ <Tooltip content={tooltip} />
63
+ </View>
64
+ )}
61
65
  {hint && !isHintInline && (
62
66
  <Text style={[selectHintStyles(themeTokens), staticStyles.hintBelow]} nativeID={hintId}>
63
67
  {hint}
@@ -84,7 +88,7 @@ const staticStyles = StyleSheet.create({
84
88
  container: {
85
89
  display: 'flex',
86
90
  flexDirection: 'row',
87
- alignItems: 'center'
91
+ alignItems: 'baseline'
88
92
  },
89
93
  containerWithHintBelow: {
90
94
  flexWrap: 'wrap'
@@ -95,5 +99,8 @@ const staticStyles = StyleSheet.create({
95
99
  hintBelow: {
96
100
  flexBasis: '100%',
97
101
  flexShrink: 0
102
+ },
103
+ tooltipAlign: {
104
+ alignSelf: 'center'
98
105
  }
99
106
  })
@@ -5,9 +5,7 @@ import InputLabel from '../InputLabel'
5
5
  import Feedback from '../Feedback'
6
6
  import StackView from '../StackView'
7
7
  import { useThemeTokens } from '../ThemeProvider'
8
- import useUniqueId from '../utils/useUniqueId'
9
-
10
- const joinDefined = (array) => array.filter((item) => item !== undefined).join(' ')
8
+ import useInputSupports from './useInputSupports'
11
9
 
12
10
  function InputSupports({
13
11
  children,
@@ -20,21 +18,12 @@ function InputSupports({
20
18
  }) {
21
19
  const { space } = useThemeTokens('InputSupports')
22
20
 
23
- const hasValidationError = validation === 'error'
24
-
25
- const inputId = useUniqueId('input')
26
- const hintId = useUniqueId('input-hint')
27
- const feedbackId = useUniqueId('input-feedback')
28
-
29
- const a11yProps = {
30
- accessibilityLabel: label,
31
- accessibilityHint: joinDefined([!hasValidationError && feedback, hint]), // native only -> replaced with describedBy on web
32
- accessibilityDescribedBy: joinDefined([
33
- !hasValidationError && feedback && feedbackId, // feedback receives a11yRole=alert on error, so there's no need to include it here
34
- hint && hintId
35
- ]), // introduced in RNW 0.15.0
36
- accessibilityInvalid: hasValidationError // introduced in RNW 0.15.0
37
- }
21
+ const { inputId, hintId, feedbackId, a11yProps } = useInputSupports({
22
+ feedback,
23
+ hint,
24
+ label,
25
+ validation
26
+ })
38
27
 
39
28
  return (
40
29
  <StackView space={space}>
@@ -0,0 +1,30 @@
1
+ import useUniqueId from '../utils/useUniqueId'
2
+
3
+ const joinDefined = (array) => array.filter((item) => item !== undefined).join(' ')
4
+
5
+ const useInputSupports = ({ label, feedback, validation, hint }) => {
6
+ const hasValidationError = validation === 'error'
7
+
8
+ const inputId = useUniqueId('input')
9
+ const hintId = useUniqueId('input-hint')
10
+ const feedbackId = useUniqueId('input-feedback')
11
+
12
+ const a11yProps = {
13
+ accessibilityLabel: label,
14
+ accessibilityHint: joinDefined([!hasValidationError && feedback, hint]), // native only -> replaced with describedBy on web
15
+ accessibilityDescribedBy: joinDefined([
16
+ !hasValidationError && feedback && feedbackId, // feedback receives a11yRole=alert on error, so there's no need to include it here
17
+ hint && hintId
18
+ ]),
19
+ accessibilityInvalid: hasValidationError
20
+ }
21
+
22
+ return {
23
+ inputId,
24
+ hintId,
25
+ feedbackId,
26
+ a11yProps
27
+ }
28
+ }
29
+
30
+ export default useInputSupports
@@ -11,27 +11,28 @@ import {
11
11
  import { resolvePressableTokens } from '../utils/pressability'
12
12
 
13
13
  import InlinePressable from './InlinePressable'
14
- import { applyTextStyles } from '../ThemeProvider'
14
+ import { applyTextStyles, applyOuterBorder } from '../ThemeProvider'
15
15
  import { IconText, iconComponentPropTypes } from '../Icon'
16
16
 
17
17
  const selectOuterBorderStyles = ({
18
18
  outerBorderColor,
19
19
  outerBorderWidth,
20
20
  outerBorderGap,
21
- outerBorderRadius,
21
+ borderRadius,
22
22
  outerBorderOutline
23
23
  }) =>
24
24
  // A view wrapper with a border on native messes up inline text alignment
25
25
  // so for now make focus styles strictly web-only
26
26
  Platform.OS === 'web'
27
27
  ? {
28
- margin: -1 * (outerBorderGap + outerBorderWidth) || 0,
29
- padding: outerBorderGap,
30
28
  // Allow theme to define outline, or, turn off outline and use border if rounded corners required
31
29
  outline: outerBorderOutline,
32
- borderWidth: outerBorderWidth,
33
- borderColor: outerBorderColor,
34
- borderRadius: outerBorderRadius,
30
+ ...applyOuterBorder({
31
+ outerBorderColor,
32
+ outerBorderWidth,
33
+ outerBorderGap,
34
+ borderRadius
35
+ }),
35
36
  // Stops focus ring stretching horizontally if parent has display: block
36
37
  // width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
37
38
  display: 'inline-flex'
@@ -104,11 +105,12 @@ const LinkBase = ({
104
105
  accessibilityRole,
105
106
  href,
106
107
  onPress: linkProps.handleHref({ href, onPress }),
107
- ...hrefAttrsProp.spread(hrefAttrs),
108
+ hrefAttrs,
108
109
  ...rest
109
110
  })
110
111
 
111
- const resolveTokens = (pressState) => resolvePressableTokens(tokens, pressState, { iconPosition })
112
+ const resolveLinkTokens = (pressState) =>
113
+ resolvePressableTokens(tokens, pressState, { iconPosition })
112
114
 
113
115
  // On web, this makes focus rings wrap only the link, not the entire block
114
116
  const blockLeftStyle = Platform.OS === 'web' && staticStyles.blockLeft
@@ -117,14 +119,14 @@ const LinkBase = ({
117
119
  <InlinePressable
118
120
  {...linkPropSet}
119
121
  style={(linkState) => {
120
- const themeTokens = resolveTokens(linkState)
122
+ const themeTokens = resolveLinkTokens(linkState)
121
123
  const outerBorderStyles = selectOuterBorderStyles(themeTokens)
122
124
  const hasIcon = Boolean(icon || themeTokens.icon)
123
125
  return [outerBorderStyles, blockLeftStyle, hasIcon && staticStyles.rowContainer]
124
126
  }}
125
127
  >
126
128
  {(linkState) => {
127
- const themeTokens = resolveTokens(linkState)
129
+ const themeTokens = resolveLinkTokens(linkState)
128
130
  const textStyles = selectTextStyles(themeTokens)
129
131
  const iconTokens = selectIconTokens(themeTokens)
130
132
 
@@ -170,7 +172,7 @@ LinkBase.propTypes = {
170
172
  iconPosition: PropTypes.oneOf(['left', 'right']),
171
173
  /**
172
174
  * On Web if href is passed, React Native Web maps this object's props to
173
- * `rel`, `target` and (>= RNW 0.15.0) `download` attrs.
175
+ * `rel`, `target` and `download` attrs.
174
176
  */
175
177
  hrefAttrs: PropTypes.shape(hrefAttrsProp.types)
176
178
  }
@@ -0,0 +1,185 @@
1
+ import React from 'react'
2
+ import {
3
+ StyleSheet,
4
+ TouchableWithoutFeedback,
5
+ View,
6
+ Modal as NativeModal,
7
+ Platform
8
+ } from 'react-native'
9
+
10
+ import PropTypes from 'prop-types'
11
+ import { applyShadowToken, useThemeTokens } from '../ThemeProvider'
12
+ import { getTokensPropType, useCopy, copyPropTypes, variantProp } from '../utils'
13
+ import { useViewport } from '../ViewportProvider'
14
+ import ButtonBase from '../Button/ButtonBase'
15
+ import dictionary from './dictionary'
16
+
17
+ const selectContainerStyles = ({
18
+ containerPaddingLeft,
19
+ containerPaddingRight,
20
+ containerPaddingTop,
21
+ containerPaddingBottom,
22
+ maxWidth,
23
+ height
24
+ }) => ({
25
+ height,
26
+ maxWidth,
27
+ paddingLeft: containerPaddingLeft,
28
+ paddingRight: containerPaddingRight,
29
+ paddingTop: containerPaddingTop,
30
+ paddingBottom: containerPaddingBottom
31
+ })
32
+
33
+ const selectModalStyles = ({
34
+ backgroundColor,
35
+ borderRadius,
36
+ height,
37
+ paddingLeft,
38
+ paddingRight,
39
+ paddingTop,
40
+ paddingBottom,
41
+ shadow
42
+ }) => ({
43
+ backgroundColor,
44
+ borderRadius,
45
+ height,
46
+ paddingLeft,
47
+ paddingRight,
48
+ paddingTop,
49
+ paddingBottom,
50
+ ...applyShadowToken(shadow)
51
+ })
52
+
53
+ const selectBackdropStyles = ({ backdropColor, backdropOpacity }) => ({
54
+ backgroundColor: backdropColor,
55
+ opacity: backdropOpacity
56
+ })
57
+
58
+ const selectCloseButtonContainerStyles = ({ paddingRight, paddingTop }) => ({
59
+ paddingRight,
60
+ paddingTop
61
+ })
62
+
63
+ const selectCloseIconProps = ({ closeIconSize, closeIconColor }) => ({
64
+ size: closeIconSize,
65
+ color: closeIconColor
66
+ })
67
+
68
+ /**
69
+ * A modal window is a secondary window that opens on top of the main one.
70
+ * Users have to interact with it before they can carry out their task and return to the main window.
71
+ * Use to reveal additional information to a user after they have performed an explicit interaction.
72
+ * They are a strongly discouraged pattern; it's preferred to have all relevant information within a page,
73
+ * and irrelevant information either linked externally or omitted.
74
+ *
75
+ * - Must only appear after a customer interaction, not on page load or any other circumstance
76
+ * - Open a modal based on explicit customer action e.g. clicking on a button/link/form field
77
+ * - Only one modal should be "current" at any time
78
+ * - Read [WebAIM's documentation](https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html) to create accessible modals
79
+ * - Don’t use modals to reinforce or repeat information already available in the parent page or view
80
+ * - Don’t use modals consecutively
81
+ */
82
+ const Modal = ({ children, isOpen, onClose, maxWidth, tokens, variant, copy }) => {
83
+ const viewport = useViewport()
84
+ const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth })
85
+
86
+ const { closeIcon: CloseIconComponent } = themeTokens
87
+
88
+ const getCopy = useCopy({ dictionary, copy })
89
+ const closeLabel = getCopy('closeButton')
90
+
91
+ const handleClose = () => {
92
+ if (typeof onClose === 'function') onClose()
93
+ }
94
+
95
+ const handleKeyUp = (event) => {
96
+ if (event.key === 'Escape') onClose()
97
+ }
98
+
99
+ if (!isOpen) {
100
+ return null
101
+ }
102
+
103
+ // TODO: replace the close button with IconButton when implemented (https://github.com/telus/universal-design-system/issues/281)
104
+ return (
105
+ <NativeModal transparent>
106
+ <View style={[staticStyles.positioningContainer]}>
107
+ <View
108
+ style={[staticStyles.sizingContainer, selectContainerStyles(themeTokens)]}
109
+ pointerEvents="box-none" // don't capture backdrop press events
110
+ >
111
+ <View style={[staticStyles.modal, selectModalStyles(themeTokens)]} onKeyUp={handleKeyUp}>
112
+ <View
113
+ style={[
114
+ staticStyles.closeButtonContainer,
115
+ selectCloseButtonContainerStyles(themeTokens)
116
+ ]}
117
+ >
118
+ <ButtonBase
119
+ onPress={handleClose}
120
+ accessibilityRole="button"
121
+ accessibilityLabel={closeLabel}
122
+ >
123
+ {
124
+ // TODO: add close button interactive states after IconButton is done
125
+ () => <CloseIconComponent {...selectCloseIconProps(themeTokens)} />
126
+ }
127
+ </ButtonBase>
128
+ </View>
129
+ {children}
130
+ </View>
131
+ </View>
132
+ {/* when a modal becomes open its first focusable element is being automatically focused */}
133
+ {/* and we prefer the close button over backdrop */}
134
+ <TouchableWithoutFeedback onPress={handleClose}>
135
+ <View style={[staticStyles.backdrop, selectBackdropStyles(themeTokens)]} />
136
+ </TouchableWithoutFeedback>
137
+ </View>
138
+ </NativeModal>
139
+ )
140
+ }
141
+
142
+ Modal.propTypes = {
143
+ children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
144
+ copy: copyPropTypes,
145
+ isOpen: PropTypes.bool,
146
+ onClose: PropTypes.func,
147
+ maxWidth: PropTypes.bool,
148
+ tokens: getTokensPropType('Modal'),
149
+ variant: variantProp.propType
150
+ }
151
+
152
+ export default Modal
153
+
154
+ const staticStyles = StyleSheet.create({
155
+ backdrop: {
156
+ position: 'absolute',
157
+ top: 0,
158
+ left: 0,
159
+ right: 0,
160
+ bottom: 0,
161
+ zIndex: -1,
162
+ ...Platform.select({
163
+ web: {
164
+ cursor: 'pointer'
165
+ }
166
+ })
167
+ },
168
+ positioningContainer: {
169
+ flexBasis: '100%',
170
+ alignItems: 'center',
171
+ justifyContent: 'center'
172
+ },
173
+ sizingContainer: {
174
+ maxHeight: '100%', // so that the container can expand up to the full viewport height
175
+ width: '100%' // ensure that the modal actually expands to the set maxWidth
176
+ },
177
+ modal: {
178
+ maxHeight: '100%' // so that the modal can expand vertically up to the sizing container's height (exclusive of its vertical padding)
179
+ },
180
+ closeButtonContainer: {
181
+ position: 'absolute',
182
+ top: 0,
183
+ right: 0
184
+ }
185
+ })
@@ -0,0 +1,9 @@
1
+ export default {
2
+ en: {
3
+ // English text from TDS Community `Modal`
4
+ closeButton: 'Close'
5
+ },
6
+ fr: {
7
+ closeButton: 'Fermer'
8
+ }
9
+ }
@@ -0,0 +1,3 @@
1
+ import Modal from './Modal'
2
+
3
+ export default Modal
@@ -0,0 +1,149 @@
1
+ import React, { useState } from 'react'
2
+ import { StyleSheet, Text, View } from 'react-native'
3
+
4
+ import PropTypes from 'prop-types'
5
+ import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
6
+ import { getTokensPropType, selectTokens, variantProp } from '../utils'
7
+ import ButtonBase from '../Button/ButtonBase'
8
+ import useCopy from '../utils/useCopy'
9
+ import dictionary from './dictionary'
10
+
11
+ const selectContainerStyles = (tokens) => ({ ...tokens })
12
+
13
+ const selectTextStyles = (tokens) => applyTextStyles(selectTokens('Typography', tokens))
14
+
15
+ const selectIconProps = ({ iconSize, iconColor }) => ({
16
+ size: iconSize,
17
+ color: iconColor
18
+ })
19
+
20
+ const selectIconContainerStyles = ({ iconGap }) => ({
21
+ paddingRight: iconGap
22
+ })
23
+
24
+ const selectDismissIconProps = ({ dismissIconSize, dismissIconColor }) => ({
25
+ size: dismissIconSize,
26
+ color: dismissIconColor
27
+ })
28
+
29
+ const selectDismissButtonContainerStyles = ({ dismissButtonGap }) => ({
30
+ paddingLeft: dismissButtonGap
31
+ })
32
+
33
+ /**
34
+ * A banner that highlights important messages:
35
+ * - Status message to show there is an error or outage of services
36
+ * - Confirmation message in response to user action
37
+ * - Account information letting the user know they have almost used all their data
38
+ *
39
+ * ## Usage criteria
40
+ * - Use simple text content only, such as bold test or links. Don’t use other complex components or paragraphs
41
+ * - Show notifications before the content that the message is related to, otherwise show at the top of the main content
42
+ * - Show system notifications at the top of the page, below the navigation, and expands the full-width of the viewport
43
+ * - When showing multiple notifications, show them in order of importance from top to bottom
44
+ * - Use variants to visually show the type of message contained within the Notification.
45
+ * The icon and colour will indicate meaning and importance
46
+ *
47
+ * ### Variants
48
+ * - Use `variant.style` to set the visual style of the notification
49
+ * - Use `dismissible` prop to enable dismissible functionality
50
+ * - Use `system` prop to set the visual style of the notification and denote an announcement from the system or application
51
+ *
52
+ * ### When to use the system prop?
53
+ * - Use `system` to show system-based messages coming from the application
54
+ * - Don’t use `system` when the message is in response to user action
55
+ *
56
+ * ## Variants
57
+ *
58
+ * #### Success
59
+ * Use the success variant to provide feedback of a successful operation. The message will include an icon to indicate meaning and importance.
60
+ *
61
+ * #### Warning
62
+ * Use the warning variant to provide feedback of a warning; users would still be able to proceed forward.
63
+ * The message will include an icon to indicate meaning and importance.
64
+ *
65
+ * #### Error
66
+ * Use the error variant to provide feedback of a failed operation. The message will include an icon to indicate meaning and importance.
67
+ *
68
+ * #### Dismissible
69
+ * Dismissible notifications should only be used for default or success notifications where there is no action needed from the user.
70
+ * If the information is passive then it should be dismissible as indicated by an interactive close button on the far right.
71
+ * If the notification requires an action then make the option(s) clear with a `ChevronLink` or `Link`.
72
+ *
73
+ * Use the `dismissible` prop to allow users to dismiss the Notification at any time. Once dismissed, the Notification is removed from the DOM.
74
+ *
75
+ * Please note:
76
+ *
77
+ * - Default and Success variants are dismissible
78
+ * - Error and Warning variants are not dismissible
79
+ *
80
+ * #### System message
81
+ * Use full-width `Notifications` to show system-based messages coming from the application, not in response to user action.
82
+ * Show system notifications at the top of the page, below the navigation, and expands the full-width of the viewport
83
+ */
84
+ const Notification = ({ children, system, dismissible, copy = 'en', tokens, variant }) => {
85
+ const [isDismissed, setIsDismissed] = useState(false)
86
+ const themeTokens = useThemeTokens('Notification', tokens, variant, { system })
87
+ const getCopy = useCopy({ dictionary, copy })
88
+
89
+ if (isDismissed) {
90
+ return null
91
+ }
92
+
93
+ const textStyles = selectTextStyles(themeTokens)
94
+
95
+ const content =
96
+ typeof children === 'string' ? <Text style={textStyles}>{children}</Text> : children
97
+
98
+ const { icon: IconComponent, dismissIcon: DismissIconComponent } = themeTokens
99
+
100
+ const onDismissPress = () => setIsDismissed(true)
101
+
102
+ // TODO: replace the dismiss button with IconButton when implemented (https://github.com/telus/universal-design-system/issues/281)
103
+ return (
104
+ <View style={[staticStyles.container, selectContainerStyles(themeTokens)]}>
105
+ {IconComponent && (
106
+ <View style={selectIconContainerStyles(themeTokens)}>
107
+ <IconComponent {...selectIconProps(themeTokens)} />
108
+ </View>
109
+ )}
110
+ <View style={staticStyles.contentContainer}>
111
+ {content && typeof content === 'function' ? content({ textStyles, variant }) : content}
112
+ </View>
113
+ {dismissible && DismissIconComponent && (
114
+ <View style={selectDismissButtonContainerStyles(themeTokens)}>
115
+ <ButtonBase
116
+ onPress={onDismissPress}
117
+ accessibilityRole="button"
118
+ accessibilityLabel={getCopy('dismiss')}
119
+ >
120
+ {() => <DismissIconComponent {...selectDismissIconProps(themeTokens)} />}
121
+ </ButtonBase>
122
+ </View>
123
+ )}
124
+ </View>
125
+ )
126
+ }
127
+
128
+ Notification.propTypes = {
129
+ children: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.func]),
130
+ system: PropTypes.bool,
131
+ dismissible: PropTypes.bool,
132
+ copy: PropTypes.oneOfType([
133
+ PropTypes.oneOf(['en', 'fr']),
134
+ PropTypes.shape({ dismiss: PropTypes.string })
135
+ ]),
136
+ tokens: getTokensPropType('Notification'),
137
+ variant: variantProp.propType
138
+ }
139
+
140
+ export default Notification
141
+
142
+ const staticStyles = StyleSheet.create({
143
+ container: {
144
+ flexDirection: 'row'
145
+ },
146
+ contentContainer: {
147
+ flex: 1
148
+ }
149
+ })
@@ -0,0 +1,8 @@
1
+ export default {
2
+ en: {
3
+ dismiss: 'Close'
4
+ },
5
+ fr: {
6
+ dismiss: 'Fermer'
7
+ }
8
+ }
@@ -0,0 +1,3 @@
1
+ import Notification from './Notification'
2
+
3
+ export default Notification