@thecb/components 10.6.1-beta.0 → 10.6.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/index.cjs.js +1055 -304
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.d.ts +42 -18
  4. package/dist/index.esm.js +1051 -304
  5. package/dist/index.esm.js.map +1 -1
  6. package/package.json +2 -2
  7. package/src/components/atoms/icons/DisabledAccountsAddIcon.js +200 -0
  8. package/src/components/atoms/icons/DisabledPaymentMethodsAddIcon.js +62 -0
  9. package/src/components/atoms/icons/DisabledPropertiesAddIcon.js +54 -0
  10. package/src/components/atoms/icons/PropertiesAddIcon.js +1 -0
  11. package/src/components/atoms/icons/WalletIconSmall.js +3 -7
  12. package/src/components/atoms/icons/icons.stories.js +11 -1
  13. package/src/components/atoms/icons/index.js +7 -1
  14. package/src/components/atoms/index.js +1 -0
  15. package/src/components/atoms/placeholder/Placeholder.js +150 -108
  16. package/src/components/atoms/placeholder/Placeholder.stories.js +2 -0
  17. package/src/components/atoms/placeholder/Placeholder.theme.js +8 -2
  18. package/src/components/atoms/spinner/Spinner.js +13 -5
  19. package/src/components/atoms/spinner/index.d.ts +4 -0
  20. package/src/components/atoms/toggle-switch/ToggleSwitch.js +33 -61
  21. package/src/components/atoms/toggle-switch/ToggleSwitch.stories.js +2 -3
  22. package/src/components/atoms/toggle-switch/ToggleSwitch.theme.js +5 -5
  23. package/src/components/atoms/wallet-name/WalletName.js +102 -0
  24. package/src/components/atoms/wallet-name/WalletName.stories.js +24 -0
  25. package/src/components/atoms/wallet-name/index.d.ts +15 -0
  26. package/src/components/atoms/wallet-name/index.js +3 -0
  27. package/src/components/molecules/editable-list/EditableList.js +3 -1
  28. package/src/components/molecules/editable-list/EditableList.stories.js +1 -3
  29. package/src/components/molecules/link-card/LinkCard.theme.js +7 -21
  30. package/src/components/molecules/modal/Modal.js +6 -217
  31. package/src/components/molecules/modal/Modal.stories.js +57 -13
  32. package/src/components/molecules/modal/ModalControlV1.js +234 -0
  33. package/src/components/molecules/modal/ModalControlV2.js +218 -0
  34. package/src/components/molecules/modal/__private__/ButtonLayoutWrapper.js +24 -0
  35. package/src/components/molecules/modal/__private__/CancelButton.js +36 -0
  36. package/src/components/molecules/modal/__private__/CloseButton.js +34 -0
  37. package/src/components/molecules/modal/__private__/CloseIconButton.js +39 -0
  38. package/src/components/molecules/modal/__private__/ContinueButton.js +45 -0
  39. package/src/components/molecules/modal/__private__/index.d.ts +59 -0
  40. package/src/components/molecules/modal/__private__/index.js +5 -0
  41. package/src/components/molecules/partial-amount-form/PartialAmountField.js +49 -0
  42. package/src/components/molecules/partial-amount-form/PartialAmountForm.js +8 -22
  43. package/src/components/molecules/radio-section/InnerRadioSection.js +7 -2
  44. package/src/components/molecules/registration-form/RegistrationForm.js +6 -3
  45. package/src/components/molecules/registration-form/RegistrationForm.state.js +4 -3
  46. package/src/constants/style_constants.d.ts +18 -6
  47. package/src/constants/style_constants.js +23 -20
  48. package/src/components/atoms/.DS_Store +0 -0
  49. package/src/components/atoms/icons/.DS_Store +0 -0
@@ -0,0 +1,234 @@
1
+ import React, { Fragment, useContext, useEffect, useRef } from "react";
2
+ import { ThemeContext } from "styled-components";
3
+ import AriaModal from "react-aria-modal";
4
+ import { WHITE, ATHENS_GREY, SILVER_GREY } from "../../../constants/colors";
5
+ import { FONT_WEIGHT_SEMIBOLD } from "../../../constants/style_constants";
6
+ import Paragraph from "../../atoms/paragraph";
7
+ import Title from "../../atoms/title";
8
+ import ButtonWithAction from "../../atoms/button-with-action";
9
+ import { Box, Stack, Cluster } from "../../atoms/layouts";
10
+
11
+ /*
12
+ Default Modal molecule
13
+ Uses react-aria-modal behind the scenes for a11y purposes
14
+ Styling accomplished with our atoms / layout primitives
15
+
16
+ Cancel button will (for now) always use hideModal as its action
17
+ Continue button takes an action, if you want to navigate to
18
+ a different route (as with a link) connect() and use "push" from @thecb/connected-react-router
19
+ */
20
+
21
+ const getApplicationNode = () => document.getElementById("root");
22
+
23
+ const Modal = ({
24
+ hideModal,
25
+ onExit = hideModal,
26
+ continueAction,
27
+ isContinueActionDisabled = false,
28
+ cancelAction,
29
+ modalOpen,
30
+ modalHeaderText,
31
+ modalBodyText,
32
+ cancelButtonText = "Cancel",
33
+ continueButtonText = "Continue",
34
+ closeButtonText = "Close",
35
+ modalHeaderBg = WHITE,
36
+ modalBodyBg = ATHENS_GREY,
37
+ useDangerButton = false,
38
+ defaultWrapper = true,
39
+ onlyCloseButton = false,
40
+ noButtons = false, // for instances where modal is closed automatically
41
+ maxHeight,
42
+ underlayClickExits = true,
43
+ noBorder,
44
+ customWidth,
45
+ isLoading,
46
+ buttonExtraStyles,
47
+ children,
48
+ dataQa = null,
49
+ initialFocusSelector = "",
50
+ blurUnderlay = true
51
+ }) => {
52
+ const { isMobile } = useContext(ThemeContext);
53
+
54
+ // `AriaModal` uses `focus-trap` as a transient dependency. It automatically looks
55
+ // for a tabbable node when the modal mounts. When it doesn't find one, it looks to
56
+ // the `fallbackFocus` option. However, React does not guarantee the ref supplied to
57
+ // this option will be populated on initial render when `focus-trap` is checking
58
+ // these option. When there are no buttons in the modal, this causes an error.
59
+ // Because `focus-trap` cannot be disabled, the ref itself requires a default value
60
+ // to satisfy `focus-trap` until React populates it with the real ref value.
61
+ //
62
+ // See:
63
+ // - https://react.dev/reference/react/useRef#caveats
64
+ // - https://github.com/davidtheclark/react-aria-modal/pull/103
65
+ // - https://github.com/focus-trap/focus-trap?tab=readme-ov-file#createoptions
66
+ const modalContainerRef = useRef("#react-aria-modal-dialog");
67
+
68
+ return (
69
+ <div ref={modalContainerRef} tabIndex="-1" data-qa={dataQa}>
70
+ {modalOpen && (
71
+ <AriaModal
72
+ focusTrapOptions={{
73
+ // fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
74
+ fallbackFocus: modalContainerRef?.current
75
+ }}
76
+ onExit={onExit}
77
+ getApplicationNode={getApplicationNode}
78
+ titleText={modalHeaderText}
79
+ underlayStyle={{
80
+ display: "flex",
81
+ flexDirection: "column",
82
+ justifyContent: "center",
83
+ alignItems: "center",
84
+ background: "rgba(41, 42, 51, 0.45)",
85
+ backdropFilter: blurUnderlay ? "blur(4px)" : "none",
86
+ WebkitBackdropFilter: blurUnderlay ? "blur(4px)" : "none"
87
+ }}
88
+ dialogStyle={{
89
+ width: customWidth || "615px",
90
+ overflow: "auto"
91
+ }}
92
+ underlayClickExits={underlayClickExits}
93
+ aria-modal={true}
94
+ initialFocus={initialFocusSelector}
95
+ focusDialog={!initialFocusSelector} // Focus the dialogue box itself if no selector for initial focus was provided
96
+ >
97
+ <Box
98
+ padding="0"
99
+ borderRadius="2px"
100
+ boxShadow="inset 0px -2px 0px 0px rgb(0, 80, 149)"
101
+ >
102
+ <Box background={modalHeaderBg} padding="1.5rem">
103
+ <Cluster justify="flex-start" align="center">
104
+ <Title as="h2" weight={FONT_WEIGHT_SEMIBOLD} fontSize="1.25rem">
105
+ {modalHeaderText}
106
+ </Title>
107
+ </Cluster>
108
+ </Box>
109
+ <Box background={modalBodyBg} padding="1.5rem">
110
+ <Stack childGap="1.5rem">
111
+ <Box
112
+ borderWidthOverride={noBorder && "0 0 2px 0"}
113
+ borderColor={!noBorder && SILVER_GREY}
114
+ padding={!noBorder && "0 0 1.5rem 0"}
115
+ extraStyles={
116
+ maxHeight ? `max-height: ${maxHeight}; overflow: auto;` : ``
117
+ }
118
+ >
119
+ {defaultWrapper ? (
120
+ <Paragraph variant="p">{modalBodyText}</Paragraph>
121
+ ) : (
122
+ <Box padding={maxHeight ? "0 0 1rem 0" : "0"}>
123
+ {modalBodyText}
124
+ </Box>
125
+ )}
126
+ </Box>
127
+ <Box padding="0">
128
+ <Stack
129
+ direction="row"
130
+ justify="flex-end"
131
+ align="center"
132
+ childGap="0rem"
133
+ >
134
+ {!noButtons && (
135
+ <>
136
+ {!onlyCloseButton ? (
137
+ <Fragment>
138
+ {isMobile ? (
139
+ <Stack childGap="1rem" direction="row">
140
+ <Box width="100%" padding="0">
141
+ <ButtonWithAction
142
+ variant="secondary"
143
+ action={
144
+ cancelAction ? cancelAction : hideModal
145
+ }
146
+ text={cancelButtonText}
147
+ dataQa={cancelButtonText}
148
+ extraStyles={buttonExtraStyles}
149
+ className="modal-cancel-button"
150
+ role="button"
151
+ name={cancelButtonText}
152
+ />
153
+ </Box>
154
+ <Box width="100%" padding="0">
155
+ <ButtonWithAction
156
+ variant={
157
+ useDangerButton ? "danger" : "primary"
158
+ }
159
+ action={continueAction}
160
+ text={continueButtonText}
161
+ dataQa={continueButtonText}
162
+ isLoading={isLoading}
163
+ disabled={isContinueActionDisabled}
164
+ extraStyles={buttonExtraStyles}
165
+ className="modal-continue-button"
166
+ role="button"
167
+ name={continueButtonText}
168
+ />
169
+ </Box>
170
+ </Stack>
171
+ ) : (
172
+ <Stack
173
+ childGap="1rem"
174
+ direction="row"
175
+ justify="flex-end"
176
+ >
177
+ <ButtonWithAction
178
+ variant="secondary"
179
+ action={
180
+ cancelAction ? cancelAction : hideModal
181
+ }
182
+ text={cancelButtonText}
183
+ dataQa={cancelButtonText}
184
+ extraStyles={buttonExtraStyles}
185
+ className="modal-cancel-button"
186
+ role="button"
187
+ name={cancelButtonText}
188
+ />
189
+ <ButtonWithAction
190
+ variant={
191
+ useDangerButton ? "danger" : "primary"
192
+ }
193
+ action={continueAction}
194
+ text={continueButtonText}
195
+ dataQa={continueButtonText}
196
+ isLoading={isLoading}
197
+ disabled={isContinueActionDisabled}
198
+ extraStyles={buttonExtraStyles}
199
+ className="modal-continue-button"
200
+ role="button"
201
+ name={continueButtonText}
202
+ />
203
+ </Stack>
204
+ )}
205
+ </Fragment>
206
+ ) : (
207
+ <Box padding="0.5rem">
208
+ <ButtonWithAction
209
+ action={hideModal}
210
+ variant="primary"
211
+ text={closeButtonText}
212
+ dataQa={closeButtonText}
213
+ extraStyles={buttonExtraStyles}
214
+ className="modal-close-button"
215
+ role="button"
216
+ name={closeButtonText}
217
+ />
218
+ </Box>
219
+ )}
220
+ </>
221
+ )}
222
+ </Stack>
223
+ </Box>
224
+ </Stack>
225
+ </Box>
226
+ </Box>
227
+ </AriaModal>
228
+ )}
229
+ {children}
230
+ </div>
231
+ );
232
+ };
233
+
234
+ export default Modal;
@@ -0,0 +1,218 @@
1
+ import React, { useContext, useRef } from "react";
2
+ import AriaModal from "react-aria-modal";
3
+ import { ThemeContext } from "styled-components";
4
+ import { WHITE, ATHENS_GREY, SILVER_GREY } from "../../../constants/colors";
5
+ import {
6
+ BORDER_RADIUS,
7
+ BORDER_THIN,
8
+ FONT_SIZE,
9
+ FONT_WEIGHT_SEMIBOLD,
10
+ SPACING
11
+ } from "../../../constants/style_constants";
12
+ import { noop } from "../../../util/general";
13
+ import Paragraph from "../../atoms/paragraph";
14
+ import Title from "../../atoms/title";
15
+ import { Box, Cluster } from "../../atoms/layouts";
16
+ import withWindowSize from "../../withWindowSize";
17
+ import {
18
+ ButtonLayoutWrapper,
19
+ CancelButton,
20
+ CloseButton,
21
+ CloseIconButton,
22
+ ContinueButton
23
+ } from "./__private__";
24
+
25
+ /*
26
+ Default Modal molecule
27
+ Uses react-aria-modal behind the scenes for a11y purposes
28
+ Styling accomplished with our atoms / layout primitives
29
+
30
+ Cancel button will (for now) always use hideModal as its action
31
+ Continue button takes an action, if you want to navigate to
32
+ a different route (as with a link) connect() and use "push" from @thecb/connected-react-router
33
+ */
34
+
35
+ const getApplicationNode = () => document.getElementById("root");
36
+
37
+ const Modal = ({
38
+ blurUnderlay = true,
39
+ buttonExtraStyles = "",
40
+ cancelAction = noop,
41
+ cancelButtonText = "Cancel",
42
+ cancelButtonVariant = "secondary",
43
+ children = [],
44
+ closeButtonText = "Close",
45
+ continueAction = noop,
46
+ continueButtonText = "Continue",
47
+ continueButtonVariant = "primary",
48
+ continueURL = "",
49
+ customWidth = "",
50
+ dataQa = null,
51
+ defaultWrapper = true,
52
+ hideModal = noop,
53
+ initialFocusSelector = "",
54
+ isContinueActionDisabled = false,
55
+ isLoading = false,
56
+ maxHeight = "",
57
+ modalBodyBg = "",
58
+ modalBodyText = "",
59
+ modalHeaderBg = "",
60
+ modalHeaderText = "",
61
+ modalOpen = false,
62
+ noButtons = false, // for instances where modal is closed automatically
63
+ onExit = hideModal,
64
+ onlyCloseButton = false,
65
+ onlyContinueButton = false,
66
+ showCloseIconButton = false,
67
+ underlayClickExits = true,
68
+ useDangerButton = false
69
+ }) => {
70
+ const { isMobile } = useContext(ThemeContext);
71
+
72
+ // `AriaModal` uses `focus-trap` as a transient dependency. It automatically looks
73
+ // for a tabbable node when the modal mounts. When it doesn't find one, it looks to
74
+ // the `fallbackFocus` option. However, React does not guarantee the ref supplied to
75
+ // this option will be populated on initial render when `focus-trap` is checking
76
+ // these option. When there are no buttons in the modal, this causes an error.
77
+ // Because `focus-trap` cannot be disabled, the ref itself requires a default value
78
+ // to satisfy `focus-trap` until React populates it with the real ref value.
79
+ //
80
+ // See:
81
+ // - https://react.dev/reference/react/useRef#caveats
82
+ // - https://github.com/davidtheclark/react-aria-modal/pull/103
83
+ // - https://github.com/focus-trap/focus-trap?tab=readme-ov-file#createoptions
84
+ const modalContainerRef = useRef("#react-aria-modal-dialog");
85
+
86
+ const hasCloseButton = onlyCloseButton && !noButtons;
87
+ const hasCancelButton = !onlyContinueButton && !onlyCloseButton && !noButtons;
88
+ const hasContinueButton =
89
+ (onlyContinueButton && !noButtons) || (!onlyCloseButton && !noButtons);
90
+
91
+ return (
92
+ <div ref={modalContainerRef} tabIndex="-1" data-qa={dataQa}>
93
+ {modalOpen && (
94
+ <AriaModal
95
+ focusTrapOptions={{
96
+ // fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
97
+ fallbackFocus: modalContainerRef?.current
98
+ }}
99
+ onExit={onExit}
100
+ getApplicationNode={getApplicationNode}
101
+ titleText={modalHeaderText}
102
+ underlayStyle={{
103
+ display: "flex",
104
+ flexDirection: "column",
105
+ justifyContent: "center",
106
+ alignItems: "center",
107
+ background: "rgba(41, 42, 51, 0.45)",
108
+ backdropFilter: blurUnderlay ? "blur(4px)" : "none",
109
+ WebkitBackdropFilter: blurUnderlay ? "blur(4px)" : "none"
110
+ }}
111
+ dialogStyle={{
112
+ borderRadius: BORDER_RADIUS.MD,
113
+ margin: SPACING.XS,
114
+ overflow: "auto",
115
+ width: isMobile ? "" : customWidth || "576px"
116
+ }}
117
+ underlayClickExits={underlayClickExits}
118
+ aria-modal={true}
119
+ initialFocus={initialFocusSelector}
120
+ focusDialog={!initialFocusSelector} // Focus the dialogue box itself if no selector for initial focus was provided
121
+ >
122
+ <Box padding="0" boxShadow="inset 0px -2px 0px 0px rgb(0, 80, 149)">
123
+ <Box
124
+ background={modalHeaderBg || WHITE}
125
+ borderColor={SILVER_GREY}
126
+ borderWidthOverride={`0 0 ${BORDER_THIN} 0`}
127
+ padding={`${SPACING.XS} ${SPACING.MD}`}
128
+ >
129
+ <Cluster
130
+ justify={showCloseIconButton ? "space-between" : "flex-start"}
131
+ align={
132
+ showCloseIconButton && isMobile ? "flex-start" : "center"
133
+ }
134
+ nowrap
135
+ >
136
+ <Title
137
+ as="h2"
138
+ weight={FONT_WEIGHT_SEMIBOLD}
139
+ fontSize={isMobile ? FONT_SIZE.MD : FONT_SIZE.LG}
140
+ >
141
+ {modalHeaderText}
142
+ </Title>
143
+ {showCloseIconButton && (
144
+ <CloseIconButton hideModal={hideModal} />
145
+ )}
146
+ </Cluster>
147
+ </Box>
148
+ <Box background={modalBodyBg || ATHENS_GREY} padding="0">
149
+ <Box
150
+ padding={SPACING.MD}
151
+ borderWidthOverride={!noButtons && `0 0 ${BORDER_THIN} 0`}
152
+ borderColor={!noButtons && SILVER_GREY}
153
+ extraStyles={
154
+ maxHeight ? `max-height: ${maxHeight}; overflow: auto;` : ``
155
+ }
156
+ >
157
+ {defaultWrapper ? (
158
+ <Paragraph variant={isMobile ? "pS" : "p"}>
159
+ {modalBodyText}
160
+ </Paragraph>
161
+ ) : (
162
+ <Box padding={maxHeight ? `0 0 ${SPACING.XS} 0` : "0"}>
163
+ {modalBodyText}
164
+ </Box>
165
+ )}
166
+ </Box>
167
+ {noButtons ? (
168
+ <></>
169
+ ) : (
170
+ <ButtonLayoutWrapper isMobile={isMobile}>
171
+ {[
172
+ hasCancelButton && (
173
+ <CancelButton
174
+ buttonExtraStyles={buttonExtraStyles}
175
+ cancelAction={cancelAction}
176
+ cancelButtonText={cancelButtonText}
177
+ cancelButtonVariant={cancelButtonVariant}
178
+ hideModal={hideModal}
179
+ isMobile={isMobile}
180
+ key="cancel"
181
+ />
182
+ ),
183
+ hasContinueButton && (
184
+ <ContinueButton
185
+ buttonExtraStyles={buttonExtraStyles}
186
+ continueAction={continueAction}
187
+ continueButtonText={continueButtonText}
188
+ continueURL={continueURL}
189
+ continueButtonVariant={continueButtonVariant}
190
+ isContinueActionDisabled={isContinueActionDisabled}
191
+ isLoading={isLoading}
192
+ isMobile={isMobile}
193
+ key="continue"
194
+ useDangerButton={useDangerButton}
195
+ />
196
+ ),
197
+ hasCloseButton && (
198
+ <CloseButton
199
+ buttonExtraStyles={buttonExtraStyles}
200
+ closeButtonText={closeButtonText}
201
+ hideModal={hideModal}
202
+ isMobile={isMobile}
203
+ key="close"
204
+ />
205
+ )
206
+ ].filter(button => button)}
207
+ </ButtonLayoutWrapper>
208
+ )}
209
+ </Box>
210
+ </Box>
211
+ </AriaModal>
212
+ )}
213
+ {children}
214
+ </div>
215
+ );
216
+ };
217
+
218
+ export default withWindowSize(Modal);
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { SPACING } from "../../../../constants/style_constants";
3
+ import { Box, Stack } from "../../../atoms/layouts";
4
+
5
+ export const ButtonLayoutWrapper = ({ children = [], isMobile = false }) => {
6
+ const safeChildren = Array.isArray(children) ? children : [children];
7
+ const flexGrow = isMobile ? "flex-grow: 1;" : "";
8
+
9
+ return (
10
+ <Box padding={SPACING.MD}>
11
+ <Stack childGap="1rem" direction="row" justify="flex-end">
12
+ {safeChildren.map((child, index) => {
13
+ return (
14
+ <Box padding="0" extraStyles={flexGrow} key={index}>
15
+ {child}
16
+ </Box>
17
+ );
18
+ })}
19
+ </Stack>
20
+ </Box>
21
+ );
22
+ };
23
+
24
+ export default ButtonLayoutWrapper;
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+ import {
3
+ BORDER_RADIUS,
4
+ FONT_SIZE
5
+ } from "../../../../constants/style_constants";
6
+ import { noop } from "../../../../util/general";
7
+ import ButtonWithAction from "../../../atoms/button-with-action/ButtonWithAction";
8
+
9
+ export const CancelButton = ({
10
+ buttonExtraStyles = "",
11
+ cancelAction = noop,
12
+ cancelButtonText = "",
13
+ cancelButtonVariant = "secondary",
14
+ hideModal = noop,
15
+ isMobile = false
16
+ }) => {
17
+ const fontSize = `font-size: ${isMobile ? FONT_SIZE.XS : FONT_SIZE.SM};`;
18
+ const width = isMobile ? "width: 100%;" : "";
19
+
20
+ return (
21
+ <ButtonWithAction
22
+ action={cancelAction ? cancelAction : hideModal}
23
+ borderRadius={BORDER_RADIUS.MD}
24
+ className="modal-cancel-button"
25
+ dataQa={cancelButtonText}
26
+ extraStyles={`${buttonExtraStyles}; margin: 0; ${width}`}
27
+ name={cancelButtonText}
28
+ role="button"
29
+ text={cancelButtonText}
30
+ textExtraStyles={`${fontSize}`}
31
+ variant={cancelButtonVariant}
32
+ />
33
+ );
34
+ };
35
+
36
+ export default CancelButton;
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import {
3
+ BORDER_RADIUS,
4
+ FONT_SIZE
5
+ } from "../../../../constants/style_constants";
6
+ import { noop } from "../../../../util/general";
7
+ import ButtonWithAction from "../../../atoms/button-with-action/ButtonWithAction";
8
+
9
+ export const CloseButton = ({
10
+ buttonExtraStyles = "",
11
+ closeButtonText = "",
12
+ hideModal = noop,
13
+ isMobile = false
14
+ }) => {
15
+ const fontSize = `font-size: ${isMobile ? FONT_SIZE.XS : FONT_SIZE.SM};`;
16
+ const width = isMobile ? "width: 100%;" : "";
17
+
18
+ return (
19
+ <ButtonWithAction
20
+ action={hideModal}
21
+ borderRadius={BORDER_RADIUS.MD}
22
+ className="modal-close-button"
23
+ dataQa={closeButtonText}
24
+ extraStyles={`${buttonExtraStyles}; margin: 0; ${width}`}
25
+ name={closeButtonText}
26
+ role="button"
27
+ text={closeButtonText}
28
+ textExtraStyles={`${fontSize}`}
29
+ variant="primary"
30
+ />
31
+ );
32
+ };
33
+
34
+ export default CloseButton;
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+ import { noop } from "../../../../util/general";
3
+ import ButtonWithAction from "../../../atoms/button-with-action/ButtonWithAction";
4
+ import { CloseIcon } from "../../../atoms/icons/CloseIcon";
5
+
6
+ export const CloseIconButton = ({
7
+ buttonExtraStyles = "",
8
+ hideModal = noop,
9
+ iconWidth = "24",
10
+ iconHeight = "24",
11
+ ariaLabel = "Close Modal"
12
+ }) => {
13
+ return (
14
+ <ButtonWithAction
15
+ action={hideModal}
16
+ aria-label={ariaLabel}
17
+ contentOverride
18
+ extraStyles={`
19
+ min-height: auto;
20
+ min-width: auto;
21
+ height: 1.5rem;
22
+ margin: 0 0 0 0.5rem;
23
+ &:focus {
24
+ outline-offset: -3px;
25
+ }
26
+ `}
27
+ variant="smallGhost"
28
+ >
29
+ <CloseIcon
30
+ role="img"
31
+ aria-hidden="true"
32
+ iconWidth={iconWidth}
33
+ iconHeight={iconHeight}
34
+ />
35
+ </ButtonWithAction>
36
+ );
37
+ };
38
+
39
+ export default CloseIconButton;
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import {
3
+ BORDER_RADIUS,
4
+ FONT_SIZE
5
+ } from "../../../../constants/style_constants";
6
+ import { noop } from "../../../../util/general";
7
+ import ButtonWithAction from "../../../atoms/button-with-action/ButtonWithAction";
8
+ import ButtonWithLink from "../../../atoms/button-with-link/ButtonWithLink";
9
+
10
+ export const ContinueButton = ({
11
+ buttonExtraStyles = "",
12
+ continueAction = noop,
13
+ continueButtonText = "",
14
+ continueURL = "",
15
+ continueButtonVariant = "primary",
16
+ isContinueActionDisabled = false,
17
+ isLoading = false,
18
+ isMobile = false,
19
+ useDangerButton = false
20
+ }) => {
21
+ const ContinueButtonAtom = continueURL ? ButtonWithLink : ButtonWithAction;
22
+ const fontSize = `font-size: ${isMobile ? FONT_SIZE.XS : FONT_SIZE.SM};`;
23
+ const width = isMobile ? "width: 100%;" : "";
24
+
25
+ return (
26
+ <ContinueButtonAtom
27
+ action={continueAction}
28
+ borderRadius={BORDER_RADIUS.MD}
29
+ className="modal-continue-button"
30
+ dataQa={continueButtonText}
31
+ disabled={isContinueActionDisabled}
32
+ extraStyles={`${buttonExtraStyles}; margin: 0; ${width}`}
33
+ isLoading={isLoading}
34
+ linkExtraStyles={`display: inline-block; ${width}`}
35
+ name={continueButtonText}
36
+ role="button"
37
+ text={continueButtonText}
38
+ textExtraStyles={`${fontSize}`}
39
+ url={continueURL}
40
+ variant={useDangerButton ? "danger" : continueButtonVariant}
41
+ />
42
+ );
43
+ };
44
+
45
+ export default ContinueButton;