@thecb/components 9.3.0-beta.1 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +850 -616
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +171 -60
- package/dist/index.esm.js +847 -616
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/.DS_Store +0 -0
- package/src/components/atoms/button-with-action/ButtonWithAction.js +76 -70
- package/src/components/atoms/checkbox/Checkbox.js +9 -4
- package/src/components/atoms/checkbox/Checkbox.stories.js +3 -3
- package/src/components/atoms/country-dropdown/CountryDropdown.js +2 -2
- package/src/components/atoms/country-dropdown/CountryDropdown.stories.js +0 -1
- package/src/components/atoms/dropdown/Dropdown.js +77 -44
- package/src/components/atoms/dropdown/Dropdown.theme.js +8 -2
- package/src/components/atoms/form-layouts/FormInput.js +2 -3
- package/src/components/atoms/form-select/FormSelect.js +25 -34
- package/src/components/atoms/form-select/FormSelect.stories.js +2 -2
- package/src/components/atoms/icons/AccountNumberImage.js +2 -0
- package/src/components/atoms/icons/BankIcon.js +2 -0
- package/src/components/atoms/icons/CheckmarkIcon.js +2 -0
- package/src/components/atoms/icons/GenericCard.js +2 -0
- package/src/components/atoms/icons/GenericCardLarge.js +2 -0
- package/src/components/atoms/icons/KebabMenuIcon.d.ts +1 -0
- package/src/components/atoms/icons/KebabMenuIcon.js +38 -0
- package/src/components/atoms/icons/RoutingNumberImage.js +2 -0
- package/src/components/atoms/icons/TrashIcon.js +42 -40
- package/src/components/atoms/icons/icons.stories.js +3 -1
- package/src/components/atoms/icons/index.d.ts +1 -0
- package/src/components/atoms/icons/index.js +3 -1
- package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.js +0 -1
- package/src/components/molecules/address-form/AddressForm.js +1 -2
- package/src/components/molecules/email-form/EmailForm.js +3 -1
- package/src/components/molecules/index.d.ts +1 -0
- package/src/components/molecules/index.js +1 -0
- package/src/components/molecules/modal/Modal.js +2 -1
- package/src/components/molecules/payment-form-ach/PaymentFormACH.js +4 -5
- package/src/components/molecules/payment-form-card/PaymentFormCard.js +5 -1
- package/src/components/molecules/phone-form/PhoneForm.js +3 -1
- package/src/components/molecules/popover/Popover.js +1 -1
- package/src/components/molecules/popup-menu/PopupMenu.js +152 -0
- package/src/components/molecules/popup-menu/PopupMenu.stories.js +40 -0
- package/src/components/molecules/popup-menu/PopupMenu.styled.js +20 -0
- package/src/components/molecules/popup-menu/PopupMenu.theme.js +11 -0
- package/src/components/molecules/popup-menu/index.d.ts +25 -0
- package/src/components/molecules/popup-menu/index.js +3 -0
- package/src/components/molecules/popup-menu/popup-menu-item/PopupMenuItem.js +79 -0
- package/src/components/molecules/popup-menu/popup-menu-item/PopupMenuItem.styled.js +27 -0
- package/src/components/molecules/popup-menu/popup-menu-item/PopupMenuItem.theme.js +23 -0
- package/src/components/molecules/radio-section/RadioSection.js +9 -2
- package/src/components/molecules/radio-section/RadioSection.stories.js +4 -2
- package/src/components/molecules/radio-section/radio-button/RadioButton.js +3 -1
- package/src/components/molecules/terms-and-conditions/TermsAndConditions.stories.js +3 -1
- package/src/components/molecules/terms-and-conditions/TermsAndConditionsControlV1.js +0 -1
- package/src/components/molecules/terms-and-conditions/TermsAndConditionsControlV2.js +5 -2
- package/src/components/molecules/toast-notification/ToastNotification.js +75 -0
- package/src/components/molecules/toast-notification/ToastNotification.stories.js +67 -0
- package/src/components/molecules/toast-notification/index.d.ts +18 -0
- package/src/components/molecules/toast-notification/index.js +3 -0
- package/src/constants/colors.d.ts +1 -0
- package/src/constants/colors.js +5 -1
- package/src/hooks/index.js +3 -0
- package/src/hooks/use-toast-notification/index.d.ts +23 -0
- package/src/hooks/use-toast-notification/index.js +38 -0
- package/src/index.d.ts +2 -1
- package/src/index.js +2 -1
- package/src/types/common/ToastVariants.ts +6 -0
- package/src/types/common/index.ts +1 -0
- package/src/util/index.js +10 -2
- package/dist/src/apps/checkout/pages/payment/sub-pages/payment-amount/PaymentAmount_old.js +0 -49322
- package/src/components/.DS_Store +0 -0
- package/src/components/atoms/.DS_Store +0 -0
- package/src/components/atoms/icons/.DS_Store +0 -0
- /package/src/{util/useOutsideClick.js → hooks/use-outside-click/index.js} +0 -0
- /package/src/{util/useScrollTo.js → hooks/use-scroll-to/index.js} +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
import Expand from "../../../util/expand";
|
|
3
|
+
|
|
4
|
+
export interface PopupMenuProps {
|
|
5
|
+
menuId?: string;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
triggerText?: string | JSX.Element;
|
|
8
|
+
hasIcon?: boolean;
|
|
9
|
+
iconHelpText?: string; // for screen-readers, required if using an icon for trigger
|
|
10
|
+
menuFocus?: boolean;
|
|
11
|
+
containerExtraStyles?: string;
|
|
12
|
+
textExtraStyles?: string;
|
|
13
|
+
minWidth?: string;
|
|
14
|
+
maxWidth?: string;
|
|
15
|
+
height?: string;
|
|
16
|
+
position?: { top: string; right: string; bottom: string; left: string };
|
|
17
|
+
transform?: string;
|
|
18
|
+
disclosedExtraStyles?: string;
|
|
19
|
+
borderColor?: string;
|
|
20
|
+
backgroundColor?: string;
|
|
21
|
+
popupExtraStyles?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const PopupMenu: React.FC<Expand<PopupMenuProps> &
|
|
25
|
+
React.HTMLAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { themeComponent } from "../../../../util/themeUtils";
|
|
3
|
+
import { Box, Text } from "../../../atoms";
|
|
4
|
+
import { fallbackValues } from "./PopupMenuItem.theme";
|
|
5
|
+
import { FONT_WEIGHT_SEMIBOLD } from "../../../../constants/style_constants";
|
|
6
|
+
import { PopupMenuItemContainer } from "./PopupMenuItem.styled";
|
|
7
|
+
|
|
8
|
+
const PopupMenuItem = ({
|
|
9
|
+
id,
|
|
10
|
+
closeMenuCallback,
|
|
11
|
+
action,
|
|
12
|
+
themeValues,
|
|
13
|
+
text,
|
|
14
|
+
hasIcon = false,
|
|
15
|
+
isDeleteAction = false,
|
|
16
|
+
icon: Icon,
|
|
17
|
+
textExtraStyles,
|
|
18
|
+
hoverStyles,
|
|
19
|
+
activeStyles,
|
|
20
|
+
extraStyles,
|
|
21
|
+
...rest
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<PopupMenuItemContainer
|
|
25
|
+
id={id}
|
|
26
|
+
role="menuItem"
|
|
27
|
+
text={text}
|
|
28
|
+
action={() => {
|
|
29
|
+
action();
|
|
30
|
+
closeMenuCallback();
|
|
31
|
+
}}
|
|
32
|
+
variant="smallGhost"
|
|
33
|
+
isDeleteAction={isDeleteAction}
|
|
34
|
+
theme={themeValues}
|
|
35
|
+
contentOverride
|
|
36
|
+
textExtraStyles={textExtraStyles}
|
|
37
|
+
hoverStyles={hoverStyles}
|
|
38
|
+
extraStyles={extraStyles}
|
|
39
|
+
activeStyles={`outline: none; ${activeStyles}`}
|
|
40
|
+
{...rest}
|
|
41
|
+
>
|
|
42
|
+
<Box
|
|
43
|
+
extraStyles={`
|
|
44
|
+
display: flex;
|
|
45
|
+
gap: 8px;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
padding: 0;
|
|
48
|
+
`}
|
|
49
|
+
>
|
|
50
|
+
{hasIcon && (
|
|
51
|
+
<Icon
|
|
52
|
+
iconFill={
|
|
53
|
+
isDeleteAction
|
|
54
|
+
? themeValues.menuItemColorDelete
|
|
55
|
+
: themeValues.menuItemColor
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
)}
|
|
59
|
+
{text && (
|
|
60
|
+
<Text
|
|
61
|
+
variant="pS"
|
|
62
|
+
weight={FONT_WEIGHT_SEMIBOLD}
|
|
63
|
+
fontFamily="Public Sans, sans-serif"
|
|
64
|
+
color={
|
|
65
|
+
isDeleteAction
|
|
66
|
+
? themeValues.menuItemColorDelete
|
|
67
|
+
: themeValues.menuItemColor
|
|
68
|
+
}
|
|
69
|
+
extraStyles={textExtraStyles}
|
|
70
|
+
>
|
|
71
|
+
{text}
|
|
72
|
+
</Text>
|
|
73
|
+
)}
|
|
74
|
+
</Box>
|
|
75
|
+
</PopupMenuItemContainer>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default themeComponent(PopupMenuItem, "PopupMenuItem", fallbackValues);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import ButtonWithAction from "../../../atoms/button-with-action/ButtonWithAction";
|
|
3
|
+
|
|
4
|
+
export const PopupMenuItemContainer = styled(ButtonWithAction)`
|
|
5
|
+
width: 100%;
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 17px 11px;
|
|
8
|
+
margin-bottom: 5px;
|
|
9
|
+
border: 0;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
text-decoration: none;
|
|
12
|
+
${({ theme, isDeleteAction }) => `
|
|
13
|
+
background-color: ${theme.menuItemBackgroundColor};
|
|
14
|
+
color: ${isDeleteAction ? theme.menuItemColorDelete : theme.menuItemColor};
|
|
15
|
+
`}
|
|
16
|
+
&:hover,
|
|
17
|
+
&:active {
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
${({ theme, isDeleteAction }) => `
|
|
20
|
+
background-color: ${
|
|
21
|
+
isDeleteAction
|
|
22
|
+
? theme.menuItemHoverBackgroundColorDelete
|
|
23
|
+
: theme.menuItemHoverBackgroundColor
|
|
24
|
+
};
|
|
25
|
+
`}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ROYAL_BLUE_VIVID,
|
|
3
|
+
CORNFLOWER_BLUE,
|
|
4
|
+
RAZZMATAZZ_RED,
|
|
5
|
+
BLUSH_RED,
|
|
6
|
+
WHITE
|
|
7
|
+
} from "../../../../constants/colors";
|
|
8
|
+
|
|
9
|
+
const menuItemBackgroundColor = WHITE;
|
|
10
|
+
const menuItemColor = ROYAL_BLUE_VIVID;
|
|
11
|
+
const menuItemColorDelete = RAZZMATAZZ_RED;
|
|
12
|
+
const menuItemHoverBackgroundColor = CORNFLOWER_BLUE;
|
|
13
|
+
const menuItemHoverBackgroundColorDelete = BLUSH_RED;
|
|
14
|
+
const menuItemHoverColor = ROYAL_BLUE_VIVID;
|
|
15
|
+
|
|
16
|
+
export const fallbackValues = {
|
|
17
|
+
menuItemBackgroundColor,
|
|
18
|
+
menuItemColor,
|
|
19
|
+
menuItemColorDelete,
|
|
20
|
+
menuItemHoverBackgroundColor,
|
|
21
|
+
menuItemHoverBackgroundColorDelete,
|
|
22
|
+
menuItemHoverColor
|
|
23
|
+
};
|
|
@@ -47,7 +47,8 @@ const RadioSection = ({
|
|
|
47
47
|
initiallyOpen = true,
|
|
48
48
|
openHeight = "auto",
|
|
49
49
|
containerStyles = "",
|
|
50
|
-
ariaDescribedBy
|
|
50
|
+
ariaDescribedBy,
|
|
51
|
+
isSectionRequired = false
|
|
51
52
|
}) => {
|
|
52
53
|
const handleKeyDown = (id, e) => {
|
|
53
54
|
if (e?.keyCode === 13 || e?.keyCode === 32) {
|
|
@@ -105,7 +106,11 @@ const RadioSection = ({
|
|
|
105
106
|
borderRadius="4px"
|
|
106
107
|
extraStyles={containerStyles}
|
|
107
108
|
>
|
|
108
|
-
<Stack
|
|
109
|
+
<Stack
|
|
110
|
+
childGap="0"
|
|
111
|
+
aria-role="radiogroup"
|
|
112
|
+
aria-required={isSectionRequired}
|
|
113
|
+
>
|
|
109
114
|
{sections
|
|
110
115
|
.filter(section => !section.hidden)
|
|
111
116
|
.map(section => (
|
|
@@ -124,6 +129,7 @@ const RadioSection = ({
|
|
|
124
129
|
role="radio"
|
|
125
130
|
aria-checked={openSection === section.id}
|
|
126
131
|
aria-disabled={section.disabled}
|
|
132
|
+
aria-required={section?.required}
|
|
127
133
|
>
|
|
128
134
|
<Stack childGap="0">
|
|
129
135
|
<Box
|
|
@@ -177,6 +183,7 @@ const RadioSection = ({
|
|
|
177
183
|
: () => toggleOpenSection(section.id)
|
|
178
184
|
}
|
|
179
185
|
tabIndex="-1"
|
|
186
|
+
isRequired={section?.required}
|
|
180
187
|
/>
|
|
181
188
|
</Box>
|
|
182
189
|
)}
|
|
@@ -49,9 +49,10 @@ const sections = [
|
|
|
49
49
|
title: "New Card",
|
|
50
50
|
content: <p>The form to add a credit card would go here.</p>,
|
|
51
51
|
rightIconsLabel: cardIconsLabel,
|
|
52
|
-
rightIcons: cardIcons
|
|
52
|
+
rightIcons: cardIcons,
|
|
53
|
+
required: true
|
|
53
54
|
},
|
|
54
|
-
{ id: "bar", title: "Bar", content: <div>Content 1</div
|
|
55
|
+
{ id: "bar", title: "Bar", content: <div>Content 1</div>, required: true },
|
|
55
56
|
{ id: "baz", title: "Baz", content: <div>Content 2</div> }
|
|
56
57
|
];
|
|
57
58
|
|
|
@@ -65,6 +66,7 @@ export const radioSection = () => {
|
|
|
65
66
|
openSection={openSection}
|
|
66
67
|
staggeredAnimation={boolean("staggeredAnimation", false, "props")}
|
|
67
68
|
sections={sections}
|
|
69
|
+
isSectionRequired={true}
|
|
68
70
|
/>
|
|
69
71
|
);
|
|
70
72
|
};
|
|
@@ -19,7 +19,8 @@ const RadioButton = ({
|
|
|
19
19
|
ariaDescribedBy = "",
|
|
20
20
|
themeValues,
|
|
21
21
|
ariaLabelledBy = "",
|
|
22
|
-
ariaLabel = null
|
|
22
|
+
ariaLabel = null,
|
|
23
|
+
isRequired = false
|
|
23
24
|
}) => {
|
|
24
25
|
const buttonBorder = {
|
|
25
26
|
onFocused: {
|
|
@@ -93,6 +94,7 @@ const RadioButton = ({
|
|
|
93
94
|
onClick={toggleRadio}
|
|
94
95
|
aria-describedby={ariaDescribedBy}
|
|
95
96
|
tabIndex="-1"
|
|
97
|
+
required={isRequired}
|
|
96
98
|
{...extraProps}
|
|
97
99
|
/>
|
|
98
100
|
<Motion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { text, boolean } from "@storybook/addon-knobs";
|
|
2
|
+
import { text, boolean, select } from "@storybook/addon-knobs";
|
|
3
3
|
|
|
4
4
|
import TermsAndConditions from "./TermsAndConditions";
|
|
5
5
|
import page from "../../../../.storybook/page";
|
|
@@ -9,11 +9,13 @@ const groupId = "props";
|
|
|
9
9
|
|
|
10
10
|
export const termsAndConditions = () => (
|
|
11
11
|
<TermsAndConditions
|
|
12
|
+
version={select("version", ["v1", "v2"], "v1", groupId)}
|
|
12
13
|
onCheck={noop}
|
|
13
14
|
isChecked={boolean("isChecked", false, groupId)}
|
|
14
15
|
html={text("html", "terms and conditions summary", groupId)}
|
|
15
16
|
terms={text("terms", "terms and conditions modal text", groupId)}
|
|
16
17
|
error={boolean("error", false, groupId)}
|
|
18
|
+
description={text("description", "I definitely agree to the", groupId)}
|
|
17
19
|
/>
|
|
18
20
|
);
|
|
19
21
|
|
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
ERROR_COLOR
|
|
10
10
|
} from "../../../constants/colors";
|
|
11
11
|
import { generateShadows } from "../../../util/generateShadows";
|
|
12
|
-
import useScrollTo from "../../../
|
|
12
|
+
import { useScrollTo } from "../../../hooks";
|
|
13
|
+
|
|
14
|
+
const TermsAndConditionsTitleDivId = "terms-and-conditions-title";
|
|
13
15
|
|
|
14
16
|
const TermsAndConditionsControlV2 = ({
|
|
15
17
|
showCheckbox = true,
|
|
@@ -57,7 +59,7 @@ const TermsAndConditionsControlV2 = ({
|
|
|
57
59
|
onChange={onCheck}
|
|
58
60
|
checkboxMargin={checkboxMargin}
|
|
59
61
|
extraStyles={`align-self: flex-start;`}
|
|
60
|
-
|
|
62
|
+
labelledById={TermsAndConditionsTitleDivId}
|
|
61
63
|
/>
|
|
62
64
|
)}
|
|
63
65
|
<Stack childGap="0.25rem" fullHeight>
|
|
@@ -66,6 +68,7 @@ const TermsAndConditionsControlV2 = ({
|
|
|
66
68
|
align="center"
|
|
67
69
|
nowrap
|
|
68
70
|
extraStyles={`padding-right: 2px; > div > * { margin: 4px 2px; };`}
|
|
71
|
+
id={TermsAndConditionsTitleDivId}
|
|
69
72
|
>
|
|
70
73
|
{description && <Text color={CHARADE_GREY}>{description}</Text>}
|
|
71
74
|
{terms && (
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Cluster } from "../../atoms/layouts";
|
|
3
|
+
import { Paragraph } from "../../atoms";
|
|
4
|
+
import {
|
|
5
|
+
SuccessfulIconMedium,
|
|
6
|
+
ErroredIcon,
|
|
7
|
+
IconQuitLarge
|
|
8
|
+
} from "../../atoms/icons";
|
|
9
|
+
import {
|
|
10
|
+
ERROR_BACKGROUND_COLOR,
|
|
11
|
+
HINT_GREEN,
|
|
12
|
+
WHITE
|
|
13
|
+
} from "../../../constants/colors";
|
|
14
|
+
import { FONT_WEIGHT_SEMIBOLD } from "../../../constants/style_constants";
|
|
15
|
+
import { generateShadows } from "../../../util/generateShadows";
|
|
16
|
+
|
|
17
|
+
const VARIANTS = {
|
|
18
|
+
SUCCESS: "success",
|
|
19
|
+
ERROR: "error"
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const ToastNotification = ({
|
|
23
|
+
variant = VARIANTS.SUCCESS,
|
|
24
|
+
message = "",
|
|
25
|
+
toastOpen,
|
|
26
|
+
closeToastNotification,
|
|
27
|
+
extraStyles,
|
|
28
|
+
minWidth = "112px",
|
|
29
|
+
maxWidth = "350px",
|
|
30
|
+
height = "56px",
|
|
31
|
+
childGap = "1rem",
|
|
32
|
+
backgroundColor
|
|
33
|
+
}) => (
|
|
34
|
+
<Box
|
|
35
|
+
onClick={closeToastNotification}
|
|
36
|
+
background={
|
|
37
|
+
backgroundColor
|
|
38
|
+
? backgroundColor
|
|
39
|
+
: variant === VARIANTS.SUCCESS
|
|
40
|
+
? HINT_GREEN
|
|
41
|
+
: variant === VARIANTS.ERROR
|
|
42
|
+
? ERROR_BACKGROUND_COLOR
|
|
43
|
+
: WHITE
|
|
44
|
+
}
|
|
45
|
+
minWidth={minWidth}
|
|
46
|
+
minHeight={height && parseInt(height) < 100 ? height : "100px"}
|
|
47
|
+
height={height ? height : "auto"}
|
|
48
|
+
tabIndex={toastOpen ? "-1" : "0"}
|
|
49
|
+
padding="0rem 1rem"
|
|
50
|
+
borderRadius="4px"
|
|
51
|
+
boxShadow={generateShadows().standard.base}
|
|
52
|
+
extraStyles={`
|
|
53
|
+
display: ${toastOpen ? "block" : "none"};
|
|
54
|
+
position: fixed; bottom: 4rem; left: 4rem;
|
|
55
|
+
${extraStyles};
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
`}
|
|
58
|
+
>
|
|
59
|
+
<Cluster align="center" childGap={childGap}>
|
|
60
|
+
{variant === VARIANTS.SUCCESS && <SuccessfulIconMedium />}
|
|
61
|
+
{variant === VARIANTS.ERROR && <ErroredIcon />}
|
|
62
|
+
<Box padding="1rem 0" maxWidth={maxWidth}>
|
|
63
|
+
<Paragraph
|
|
64
|
+
weight={FONT_WEIGHT_SEMIBOLD}
|
|
65
|
+
extraStyles={"word-break: break-word;"}
|
|
66
|
+
>
|
|
67
|
+
{message}
|
|
68
|
+
</Paragraph>
|
|
69
|
+
</Box>
|
|
70
|
+
<IconQuitLarge />
|
|
71
|
+
</Cluster>
|
|
72
|
+
</Box>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
export default ToastNotification;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import ToastNotification from "./ToastNotification";
|
|
3
|
+
import page from "../../../../.storybook/page";
|
|
4
|
+
import { useToastNotification } from "../../../hooks";
|
|
5
|
+
import { ToastVariants } from "../../../types/common";
|
|
6
|
+
|
|
7
|
+
export const toastNotificationSuccess = () => {
|
|
8
|
+
const {
|
|
9
|
+
isToastOpen,
|
|
10
|
+
toastVariant,
|
|
11
|
+
toastMessage,
|
|
12
|
+
showToast,
|
|
13
|
+
hideToast
|
|
14
|
+
} = useToastNotification();
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
showToast({
|
|
18
|
+
message: "Success!",
|
|
19
|
+
variant: ToastVariants.SUCCESS
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<ToastNotification
|
|
25
|
+
variant={toastVariant}
|
|
26
|
+
message={toastMessage}
|
|
27
|
+
toastOpen={isToastOpen}
|
|
28
|
+
closeToastNotification={() => hideToast()}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
toastNotificationSuccess.storyName = "Success Toast";
|
|
34
|
+
|
|
35
|
+
export const toastNotificationError = () => {
|
|
36
|
+
const {
|
|
37
|
+
isToastOpen,
|
|
38
|
+
toastVariant,
|
|
39
|
+
toastMessage,
|
|
40
|
+
showToast,
|
|
41
|
+
hideToast
|
|
42
|
+
} = useToastNotification();
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
showToast({
|
|
46
|
+
message: "An error occurred",
|
|
47
|
+
variant: ToastVariants.ERROR
|
|
48
|
+
});
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<ToastNotification
|
|
53
|
+
variant={toastVariant}
|
|
54
|
+
message={toastMessage}
|
|
55
|
+
toastOpen={isToastOpen}
|
|
56
|
+
closeToastNotification={() => hideToast()}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
toastNotificationError.storyName = "Error Toast";
|
|
61
|
+
|
|
62
|
+
const story = page({
|
|
63
|
+
title: "Components|Molecules/ToastNotification",
|
|
64
|
+
Component: ToastNotification
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export default story;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Expand from "../../../util/expand";
|
|
3
|
+
|
|
4
|
+
export interface ToastNotificationProps {
|
|
5
|
+
variant?: string;
|
|
6
|
+
message: string;
|
|
7
|
+
toastOpen: boolean;
|
|
8
|
+
closeToastNotification: (event?: React.MouseEvent<HTMLElement>) => void;
|
|
9
|
+
extraStyles?: string;
|
|
10
|
+
minWidth?: string;
|
|
11
|
+
maxWidth?: string;
|
|
12
|
+
height?: string;
|
|
13
|
+
childGap?: string;
|
|
14
|
+
backgroundColor?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ToastNotification: React.FC<Expand<ToastNotificationProps> &
|
|
18
|
+
React.HTMLAttributes<HTMLElement>>;
|
package/src/constants/colors.js
CHANGED
|
@@ -56,6 +56,7 @@ const INFO_BLUE = "#E4F4FD";
|
|
|
56
56
|
const CORNFLOWER_BLUE = "#EBEFFB";
|
|
57
57
|
const HOVER_LIGHT_BLUE = "#EFFAFF";
|
|
58
58
|
const MATISSE_BLUE = "#15749D";
|
|
59
|
+
const MATISSE_BLUE_DARK = "#105C7D";
|
|
59
60
|
const ROYAL_BLUE = "#3181E3";
|
|
60
61
|
const ROYAL_BLUE_VIVID = "#3B5BDB";
|
|
61
62
|
const ASTRAL_BLUE = "#3176AA";
|
|
@@ -90,6 +91,7 @@ const BLUSH_RED = "#FFF0F5";
|
|
|
90
91
|
|
|
91
92
|
// Second level color constants
|
|
92
93
|
const ERROR_COLOR = RAZZMATAZZ_RED;
|
|
94
|
+
const ERROR_BACKGROUND_COLOR = "#FFF4F8";
|
|
93
95
|
|
|
94
96
|
// These colors are sequestered so that the alert component can reference them // by type of alert
|
|
95
97
|
const ALERT_COLORS = {
|
|
@@ -192,6 +194,7 @@ export {
|
|
|
192
194
|
BOSTON_BLUE,
|
|
193
195
|
HOVER_LIGHT_BLUE,
|
|
194
196
|
MATISSE_BLUE,
|
|
197
|
+
MATISSE_BLUE_DARK,
|
|
195
198
|
ROYAL_BLUE,
|
|
196
199
|
ROYAL_BLUE_VIVID,
|
|
197
200
|
ASTRAL_BLUE,
|
|
@@ -221,5 +224,6 @@ export {
|
|
|
221
224
|
RASPBERRY,
|
|
222
225
|
ALERT_COLORS,
|
|
223
226
|
PILL_COLORS,
|
|
224
|
-
ERROR_COLOR
|
|
227
|
+
ERROR_COLOR,
|
|
228
|
+
ERROR_BACKGROUND_COLOR
|
|
225
229
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ToastVariants } from "../../types/common";
|
|
2
|
+
|
|
3
|
+
export interface UseToastOptions {
|
|
4
|
+
timeout?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface UseToastResult {
|
|
8
|
+
isToastOpen: boolean;
|
|
9
|
+
toastVariant: string | ToastVariants;
|
|
10
|
+
toastMessage: string;
|
|
11
|
+
showToast: ({
|
|
12
|
+
message,
|
|
13
|
+
variant
|
|
14
|
+
}: {
|
|
15
|
+
message: string;
|
|
16
|
+
variant: string | ToastVariants;
|
|
17
|
+
}) => void;
|
|
18
|
+
hideToast: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default function useToastNotification(
|
|
22
|
+
options?: UseToastOptions
|
|
23
|
+
): UseToastResult;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
const initialToastState = {
|
|
4
|
+
isOpen: false,
|
|
5
|
+
variant: "",
|
|
6
|
+
message: ""
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const useToastNotification = ({ timeout = 5000 } = {}) => {
|
|
10
|
+
const [toastState, setToastState] = useState(initialToastState);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (toastState.isOpen) {
|
|
14
|
+
setTimeout(() => {
|
|
15
|
+
setToastState(initialToastState);
|
|
16
|
+
}, timeout);
|
|
17
|
+
}
|
|
18
|
+
}, [timeout, toastState.isOpen]);
|
|
19
|
+
|
|
20
|
+
const showToast = ({ message, variant }) =>
|
|
21
|
+
setToastState({
|
|
22
|
+
isOpen: true,
|
|
23
|
+
variant,
|
|
24
|
+
message
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const hideToast = () => setToastState(initialToastState);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
isToastOpen: toastState.isOpen,
|
|
31
|
+
toastVariant: toastState.variant,
|
|
32
|
+
toastMessage: toastState.message,
|
|
33
|
+
showToast,
|
|
34
|
+
hideToast
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default useToastNotification;
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -4,4 +4,5 @@ export { default as FieldActions } from "./FieldActions";
|
|
|
4
4
|
export { default as FormSelectOption } from "./FormSelectOption";
|
|
5
5
|
export { default as SearchableSelectOption } from "./SearchableSelectOption";
|
|
6
6
|
export { default as ErrorMessageDictionary } from "./ErrorMessageDictionary";
|
|
7
|
+
export { default as ToastVariants } from "./ToastVariants";
|
|
7
8
|
export * from "./FieldActions";
|
package/src/util/index.js
CHANGED
|
@@ -2,6 +2,14 @@ import * as formats from "./formats";
|
|
|
2
2
|
import * as general from "./general";
|
|
3
3
|
import * as theme from "./themeUtils";
|
|
4
4
|
import useFocusInvalidInput from "./focusFirstInvalidInputHook";
|
|
5
|
-
import useOutsideClick from "
|
|
5
|
+
import useOutsideClick from "../hooks/use-outside-click";
|
|
6
|
+
import useToastNotification from "../hooks/use-toast-notification";
|
|
6
7
|
|
|
7
|
-
export {
|
|
8
|
+
export {
|
|
9
|
+
formats,
|
|
10
|
+
general,
|
|
11
|
+
theme,
|
|
12
|
+
useFocusInvalidInput,
|
|
13
|
+
useOutsideClick,
|
|
14
|
+
useToastNotification
|
|
15
|
+
};
|