@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.
- package/.ultra.cache.json +1 -1
- package/CHANGELOG.md +27 -0
- package/__fixtures__/Accessible.js +33 -0
- package/__fixtures__/Accessible.native.js +32 -0
- package/__fixtures__/testTheme.js +429 -29
- package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
- package/__tests__/Button/ButtonGroup.test.jsx +2 -2
- package/__tests__/Checkbox/CheckboxGroup.test.jsx +247 -0
- package/__tests__/Icon/Icon.test.jsx +3 -3
- package/__tests__/Modal/Modal.test.jsx +47 -0
- package/__tests__/Notification/Notification.test.jsx +20 -0
- package/__tests__/Pagination/Pagination.test.jsx +2 -2
- package/__tests__/Progress/Progress.test.jsx +79 -0
- package/__tests__/Radio/RadioGroup.test.jsx +221 -0
- package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
- package/__tests__/RadioCard/RadioCardGroup.test.jsx +247 -0
- package/__tests__/Search/Search.test.jsx +72 -0
- package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
- package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
- package/__tests__/Tabs/Tabs.test.jsx +200 -0
- package/__tests__/Tags/Tags.test.jsx +1 -1
- package/__tests__/utils/input.test.js +58 -0
- package/__tests__/utils/useCopy.test.js +14 -3
- package/babel.config.js +20 -0
- package/jest.config.js +1 -1
- package/lib/A11yInfoProvider/index.js +54 -26
- package/lib/A11yText/index.js +37 -14
- package/lib/ActivityIndicator/Spinner.js +78 -0
- package/lib/ActivityIndicator/Spinner.native.js +121 -87
- package/lib/ActivityIndicator/index.js +28 -12
- package/lib/ActivityIndicator/shared.js +27 -12
- package/lib/BaseProvider/index.js +34 -11
- package/lib/Box/Box.js +54 -31
- package/lib/Box/index.js +13 -2
- package/lib/Button/Button.js +32 -11
- package/lib/Button/ButtonBase.js +85 -78
- package/lib/Button/ButtonGroup.js +94 -70
- package/lib/Button/ButtonLink.js +38 -15
- package/lib/Button/index.js +31 -4
- package/lib/Button/propTypes.js +32 -9
- package/lib/Card/Card.js +36 -41
- package/lib/Card/CardBase.js +78 -0
- package/lib/Card/PressableCardBase.js +137 -0
- package/lib/Card/index.js +40 -2
- package/lib/Checkbox/Checkbox.js +139 -103
- package/lib/Checkbox/CheckboxGroup.js +231 -0
- package/lib/Checkbox/CheckboxInput.js +74 -0
- package/lib/Checkbox/CheckboxInput.native.js +9 -1
- package/lib/Checkbox/index.js +21 -2
- package/lib/Divider/Divider.js +50 -24
- package/lib/Divider/index.js +13 -2
- package/lib/ExpandCollapse/Accordion.js +20 -7
- package/lib/ExpandCollapse/Control.js +50 -27
- package/lib/ExpandCollapse/ExpandCollapse.js +41 -24
- package/lib/ExpandCollapse/Panel.js +75 -37
- package/lib/ExpandCollapse/index.js +25 -7
- package/lib/Feedback/Feedback.js +69 -40
- package/lib/Feedback/index.js +13 -2
- package/lib/Fieldset/Fieldset.js +160 -0
- package/lib/Fieldset/FieldsetContainer.js +41 -0
- package/lib/Fieldset/FieldsetContainer.native.js +33 -0
- package/lib/Fieldset/Legend.js +33 -0
- package/lib/Fieldset/Legend.native.js +43 -0
- package/lib/Fieldset/cssReset.js +21 -0
- package/lib/Fieldset/index.js +13 -0
- package/lib/FlexGrid/Col/Col.js +67 -38
- package/lib/FlexGrid/Col/index.js +13 -2
- package/lib/FlexGrid/FlexGrid.js +70 -45
- package/lib/FlexGrid/Row/Row.js +48 -27
- package/lib/FlexGrid/Row/index.js +13 -2
- package/lib/FlexGrid/helpers/index.js +9 -1
- package/lib/FlexGrid/index.js +13 -2
- package/lib/FlexGrid/providers/GutterContext.js +15 -3
- package/lib/Icon/Icon.js +46 -44
- package/lib/Icon/IconText.js +49 -21
- package/lib/Icon/index.js +31 -4
- package/lib/InputLabel/InputLabel.js +70 -36
- package/lib/InputLabel/LabelContent.js +31 -0
- package/lib/InputLabel/LabelContent.native.js +9 -1
- package/lib/InputLabel/index.js +13 -2
- package/lib/InputSupports/InputSupports.js +62 -48
- package/lib/InputSupports/index.js +13 -2
- package/lib/InputSupports/propTypes.js +19 -8
- package/lib/InputSupports/useInputSupports.js +41 -0
- package/lib/Link/ChevronLink.js +33 -16
- package/lib/Link/InlinePressable.js +50 -0
- package/lib/Link/InlinePressable.native.js +34 -11
- package/lib/Link/Link.js +25 -9
- package/lib/Link/LinkBase.js +87 -57
- package/lib/Link/TextButton.js +32 -13
- package/lib/Link/index.js +39 -5
- package/lib/List/List.js +51 -23
- package/lib/List/ListItem.js +70 -40
- package/lib/List/index.js +13 -2
- package/lib/Modal/Modal.js +226 -0
- package/lib/Modal/dictionary.js +16 -0
- package/lib/Modal/index.js +13 -0
- package/lib/Notification/Notification.js +200 -0
- package/lib/Notification/dictionary.js +15 -0
- package/lib/Notification/index.js +13 -0
- package/lib/Pagination/PageButton.js +47 -25
- package/lib/Pagination/Pagination.js +70 -40
- package/lib/Pagination/SideButton.js +63 -37
- package/lib/Pagination/dictionary.js +9 -2
- package/lib/Pagination/index.js +13 -2
- package/lib/Pagination/usePagination.js +12 -2
- package/lib/Progress/Progress.js +99 -0
- package/lib/Progress/ProgressBar.js +146 -0
- package/lib/Progress/ProgressBarBackground.js +57 -0
- package/lib/Progress/index.js +16 -0
- package/lib/Radio/Radio.js +110 -109
- package/lib/Radio/RadioButton.js +141 -0
- package/lib/Radio/RadioGroup.js +233 -0
- package/lib/Radio/RadioInput.js +76 -0
- package/lib/Radio/RadioInput.native.js +9 -1
- package/lib/Radio/index.js +21 -2
- package/lib/RadioCard/RadioCard.js +240 -0
- package/lib/RadioCard/RadioCardGroup.js +251 -0
- package/lib/RadioCard/index.js +21 -0
- package/lib/Search/Search.js +243 -0
- package/lib/Search/dictionary.js +19 -0
- package/lib/Search/index.js +13 -0
- package/lib/Select/Group.js +33 -0
- package/lib/Select/Group.native.js +16 -5
- package/lib/Select/Item.js +29 -0
- package/lib/Select/Item.native.js +14 -4
- package/lib/Select/Picker.js +79 -0
- package/lib/Select/Picker.native.js +52 -24
- package/lib/Select/Select.js +110 -82
- package/lib/Select/index.js +19 -6
- package/lib/SideNav/Item.js +54 -33
- package/lib/SideNav/ItemContent.js +41 -15
- package/lib/SideNav/ItemsGroup.js +46 -27
- package/lib/SideNav/SideNav.js +92 -69
- package/lib/SideNav/index.js +15 -1
- package/lib/Skeleton/Skeleton.js +55 -37
- package/lib/Skeleton/index.js +13 -2
- package/lib/Skeleton/skeleton.constant.js +12 -0
- package/lib/Skeleton/skeletonWebAnimation.js +27 -0
- package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
- package/lib/Spacer/Spacer.js +31 -12
- package/lib/Spacer/index.js +13 -2
- package/lib/StackView/StackView.js +49 -27
- package/lib/StackView/StackWrap.js +33 -10
- package/lib/StackView/StackWrap.native.js +13 -2
- package/lib/StackView/StackWrapBox.js +46 -24
- package/lib/StackView/StackWrapGap.js +43 -22
- package/lib/StackView/common.js +19 -4
- package/lib/StackView/getStackedContent.js +49 -19
- package/lib/StackView/index.js +29 -5
- package/lib/StepTracker/Step.js +245 -0
- package/lib/StepTracker/StepTracker.js +197 -0
- package/lib/StepTracker/dictionary.js +17 -0
- package/lib/StepTracker/index.js +13 -0
- package/lib/Tabs/HorizontalScroll.js +199 -0
- package/lib/Tabs/ScrollViewEnd.js +66 -0
- package/lib/Tabs/ScrollViewEnd.native.js +41 -0
- package/lib/Tabs/Tabs.js +117 -0
- package/lib/Tabs/TabsItem.js +234 -0
- package/lib/Tabs/TabsScrollButton.js +121 -0
- package/lib/Tabs/dictionary.js +18 -0
- package/lib/Tabs/index.js +13 -0
- package/lib/Tabs/itemPositions.js +128 -0
- package/lib/Tags/Tags.js +130 -97
- package/lib/Tags/index.js +13 -2
- package/lib/TextInput/TextArea.js +51 -24
- package/lib/TextInput/TextInput.js +40 -19
- package/lib/TextInput/TextInputBase.js +78 -55
- package/lib/TextInput/index.js +23 -3
- package/lib/TextInput/propTypes.js +18 -7
- package/lib/ThemeProvider/ThemeProvider.js +38 -14
- package/lib/ThemeProvider/index.js +61 -6
- package/lib/ThemeProvider/useSetTheme.js +14 -5
- package/lib/ThemeProvider/useTheme.js +13 -4
- package/lib/ThemeProvider/useThemeTokens.js +32 -16
- package/lib/ThemeProvider/utils/index.js +31 -2
- package/lib/ThemeProvider/utils/styles.js +52 -16
- package/lib/ThemeProvider/utils/theme-tokens.js +94 -16
- package/lib/ToggleSwitch/ToggleSwitch.js +75 -51
- package/lib/ToggleSwitch/index.js +13 -2
- package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +22 -18
- package/lib/Tooltip/Backdrop.native.js +39 -15
- package/lib/Tooltip/Tooltip.js +112 -70
- package/lib/Tooltip/dictionary.js +9 -2
- package/lib/Tooltip/getTooltipPosition.js +9 -1
- package/lib/Tooltip/index.js +13 -2
- package/lib/TooltipButton/TooltipButton.js +57 -38
- package/lib/TooltipButton/index.js +13 -2
- package/lib/Typography/Typography.js +57 -27
- package/lib/Typography/index.js +13 -2
- package/lib/ViewportProvider/ViewportProvider.js +34 -13
- package/lib/ViewportProvider/index.js +28 -3
- package/lib/ViewportProvider/useViewport.js +15 -3
- package/lib/ViewportProvider/useViewportListener.js +24 -10
- package/lib/index.js +509 -33
- package/lib/utils/a11y/index.js +18 -1
- package/lib/utils/a11y/textSize.js +23 -7
- package/lib/utils/animation/index.js +15 -2
- package/lib/utils/animation/useVerticalExpandAnimation.js +28 -11
- package/lib/utils/children.js +87 -0
- package/lib/utils/index.js +163 -10
- package/lib/utils/info/index.js +18 -6
- package/lib/utils/info/platform/index.js +19 -7
- package/lib/utils/info/platform/platform.android.js +8 -1
- package/lib/utils/info/platform/platform.ios.js +8 -1
- package/lib/utils/info/platform/platform.js +8 -0
- package/lib/utils/info/platform/platform.native.js +8 -1
- package/lib/utils/info/versions.js +15 -4
- package/lib/utils/input.js +51 -33
- package/lib/utils/pressability.js +38 -10
- package/lib/utils/propTypes.js +217 -125
- package/lib/utils/useCopy.js +40 -5
- package/lib/utils/useHash.js +48 -0
- package/lib/utils/useHash.native.js +15 -0
- package/lib/utils/useResponsiveProp.js +21 -9
- package/lib/utils/useSpacingScale.js +21 -9
- package/lib/utils/useUniqueId.js +13 -4
- package/package.json +7 -6
- package/release-context.json +4 -4
- package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +0 -0
- package/src/Box/Box.jsx +11 -4
- package/src/Button/Button.jsx +3 -2
- package/src/Button/ButtonBase.jsx +27 -36
- package/src/Button/ButtonGroup.jsx +2 -2
- package/src/Button/ButtonLink.jsx +3 -2
- package/src/Button/propTypes.js +12 -2
- package/src/Card/Card.jsx +4 -30
- package/src/Card/CardBase.jsx +57 -0
- package/src/Card/PressableCardBase.jsx +112 -0
- package/src/Card/index.js +3 -0
- package/src/Checkbox/Checkbox.jsx +10 -11
- package/src/Checkbox/CheckboxGroup.jsx +196 -0
- package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
- package/src/Checkbox/index.js +2 -0
- package/src/ExpandCollapse/Control.jsx +1 -1
- package/src/Feedback/Feedback.jsx +1 -1
- package/src/Fieldset/Fieldset.jsx +129 -0
- package/src/Fieldset/FieldsetContainer.jsx +22 -0
- package/src/Fieldset/FieldsetContainer.native.jsx +16 -0
- package/src/Fieldset/Legend.jsx +16 -0
- package/src/Fieldset/Legend.native.jsx +22 -0
- package/src/Fieldset/cssReset.js +14 -0
- package/src/Fieldset/index.js +3 -0
- package/src/Icon/Icon.jsx +14 -23
- package/src/Icon/IconText.jsx +2 -2
- package/src/Icon/index.js +2 -2
- package/src/InputLabel/InputLabel.jsx +9 -2
- package/src/InputLabel/{LabelContent.web.jsx → LabelContent.jsx} +0 -0
- package/src/InputSupports/InputSupports.jsx +7 -18
- package/src/InputSupports/useInputSupports.js +30 -0
- package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +0 -0
- package/src/Link/LinkBase.jsx +14 -12
- package/src/Modal/Modal.jsx +185 -0
- package/src/Modal/dictionary.js +9 -0
- package/src/Modal/index.js +3 -0
- package/src/Notification/Notification.jsx +149 -0
- package/src/Notification/dictionary.js +8 -0
- package/src/Notification/index.js +3 -0
- package/src/Progress/Progress.jsx +77 -0
- package/src/Progress/ProgressBar.jsx +110 -0
- package/src/Progress/ProgressBarBackground.jsx +34 -0
- package/src/Progress/index.js +6 -0
- package/src/Radio/Radio.jsx +19 -56
- package/src/Radio/RadioButton.jsx +131 -0
- package/src/Radio/RadioGroup.jsx +198 -0
- package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
- package/src/Radio/index.js +2 -0
- package/src/RadioCard/RadioCard.jsx +191 -0
- package/src/RadioCard/RadioCardGroup.jsx +211 -0
- package/src/RadioCard/index.js +5 -0
- package/src/Search/Search.jsx +204 -0
- package/src/Search/dictionary.js +12 -0
- package/src/Search/index.js +3 -0
- package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
- package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
- package/src/Select/{Picker.web.jsx → Picker.jsx} +0 -0
- package/src/Select/Select.jsx +12 -22
- package/src/SideNav/Item.jsx +2 -2
- package/src/Skeleton/Skeleton.jsx +17 -20
- package/src/Skeleton/skeleton.constant.js +3 -0
- package/src/Skeleton/skeletonWebAnimation.js +13 -0
- package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
- package/src/StackView/StackView.jsx +10 -3
- package/src/StackView/StackWrap.jsx +9 -1
- package/src/StackView/StackWrapBox.jsx +4 -3
- package/src/StackView/StackWrapGap.jsx +3 -3
- package/src/StackView/getStackedContent.jsx +8 -2
- package/src/StepTracker/Step.jsx +202 -0
- package/src/StepTracker/StepTracker.jsx +163 -0
- package/src/StepTracker/dictionary.js +10 -0
- package/src/StepTracker/index.js +3 -0
- package/src/Tabs/HorizontalScroll.jsx +165 -0
- package/src/Tabs/ScrollViewEnd.jsx +53 -0
- package/src/Tabs/ScrollViewEnd.native.jsx +24 -0
- package/src/Tabs/Tabs.jsx +89 -0
- package/src/Tabs/TabsItem.jsx +204 -0
- package/src/Tabs/TabsScrollButton.jsx +100 -0
- package/src/Tabs/dictionary.js +11 -0
- package/src/Tabs/index.js +3 -0
- package/src/Tabs/itemPositions.js +101 -0
- package/src/Tags/Tags.jsx +2 -1
- package/src/TextInput/TextInputBase.jsx +12 -22
- package/src/ThemeProvider/useThemeTokens.js +2 -2
- package/src/ThemeProvider/utils/styles.js +18 -5
- package/src/ThemeProvider/utils/theme-tokens.js +46 -5
- package/src/ToggleSwitch/ToggleSwitch.jsx +2 -3
- package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
- package/src/Tooltip/Tooltip.jsx +1 -1
- package/src/TooltipButton/TooltipButton.jsx +23 -27
- package/src/Typography/Typography.jsx +6 -5
- package/src/index.js +20 -2
- package/src/utils/children.jsx +66 -0
- package/src/utils/index.js +3 -0
- package/src/utils/info/platform/platform.js +1 -0
- package/src/utils/info/versions.js +2 -2
- package/src/utils/input.js +20 -12
- package/src/utils/pressability.js +4 -0
- package/src/utils/propTypes.js +98 -34
- package/src/utils/useCopy.js +30 -4
- package/src/utils/useHash.js +34 -0
- package/src/utils/useHash.native.js +6 -0
- package/stories/A11yText/A11yText.stories.jsx +4 -8
- package/stories/Checkbox/Checkbox.stories.jsx +24 -1
- package/stories/Icon/Icon.stories.jsx +6 -5
- package/stories/Modal/Modal.stories.jsx +29 -0
- package/stories/Notification/Notification.stories.jsx +82 -0
- package/stories/Progress/Progress.stories.jsx +93 -0
- package/stories/Radio/Radio.stories.jsx +23 -36
- package/stories/RadioCard/RadioCard.stories.jsx +98 -0
- package/stories/Search/Search.stories.jsx +16 -0
- package/stories/StepTracker/StepTracker.stories.jsx +71 -0
- package/stories/Tabs/Tabs.stories.jsx +97 -0
- package/stories/{platform-supports.web.jsx → platform-supports.jsx} +0 -0
- package/__fixtures__/accessible.icon.svg +0 -6
- package/babel.config.json +0 -8
- package/lib/ActivityIndicator/Spinner.web.js +0 -55
- package/lib/Checkbox/CheckboxInput.web.js +0 -57
- package/lib/InputLabel/LabelContent.web.js +0 -17
- package/lib/Link/InlinePressable.web.js +0 -32
- package/lib/Radio/RadioInput.web.js +0 -59
- package/lib/Select/Group.web.js +0 -18
- package/lib/Select/Item.web.js +0 -15
- package/lib/Select/Picker.web.js +0 -63
- package/lib/config/svgr-icons-web.js +0 -9
- package/lib/config/svgr-icons.js +0 -52
- package/lib/utils/info/platform/platform.web.js +0 -1
- package/src/config/svgr-icons-web.js +0 -11
- package/src/config/svgr-icons.js +0 -46
- 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 = ({
|
|
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
|
-
<
|
|
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
|
-
|
|
52
|
+
accessibilityLabel: PropTypes.string,
|
|
48
53
|
/**
|
|
49
|
-
*
|
|
54
|
+
* controls whether the icon size should be proportionate to any accessibility-related font scaling.
|
|
50
55
|
*/
|
|
51
|
-
|
|
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
|
-
*
|
|
72
|
-
*
|
|
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
|
-
|
|
65
|
+
icon: PropTypes.elementType.isRequired
|
|
75
66
|
}
|
|
76
67
|
|
|
77
68
|
export default Icon
|
package/src/Icon/IconText.jsx
CHANGED
|
@@ -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
|
|
1
|
+
import Icon, { iconComponentPropTypes } from './Icon'
|
|
2
2
|
import IconText from './IconText'
|
|
3
3
|
|
|
4
4
|
export default Icon
|
|
5
|
-
export { iconComponentPropTypes,
|
|
5
|
+
export { iconComponentPropTypes, IconText }
|
|
@@ -57,7 +57,11 @@ function InputLabel({
|
|
|
57
57
|
{hint}
|
|
58
58
|
</Text>
|
|
59
59
|
)}
|
|
60
|
-
{hasTooltip &&
|
|
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: '
|
|
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
|
})
|
|
File without changes
|
|
@@ -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
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
File without changes
|
package/src/Link/LinkBase.jsx
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
108
|
+
hrefAttrs,
|
|
108
109
|
...rest
|
|
109
110
|
})
|
|
110
111
|
|
|
111
|
-
const
|
|
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 =
|
|
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 =
|
|
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
|
|
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,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
|
+
})
|