@thecb/components 10.5.0-beta.1 → 10.5.0-beta.3
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 +39 -10
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +39 -10
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/modal/Modal.stories.js +13 -12
- package/src/components/molecules/modal/ModalControlV1.js +17 -4
- package/src/components/molecules/modal/ModalControlV2.js +19 -3
package/package.json
CHANGED
|
@@ -24,22 +24,23 @@ export const modalV1 = () => (
|
|
|
24
24
|
Modal Link
|
|
25
25
|
</Text>
|
|
26
26
|
)}
|
|
27
|
-
|
|
28
|
-
continueAction={noop}
|
|
29
|
-
modalOpen={boolean("modalOpen", true, groupId)}
|
|
30
|
-
modalHeaderText={text("modalHeaderText", "Modal Header Text", groupId)}
|
|
31
|
-
modalBodyText={text("modalBodyText", "Modal Body Text", groupId)}
|
|
27
|
+
blurUnderlay={boolean("blurUnderlay", true, groupId)}
|
|
32
28
|
cancelButtonText={text("cancelButtonText", "Cancel", groupId)}
|
|
29
|
+
continueAction={noop}
|
|
33
30
|
continueButtonText={text("continueButtonText", "Continue", groupId)}
|
|
34
|
-
modalHeaderBg={text("modalHeaderBg", "white", groupId)}
|
|
35
|
-
modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
|
|
36
|
-
useDangerButton={boolean("useDangerButton", false, groupId)}
|
|
37
31
|
defaultWrapper={boolean("defaultWrapper", true, groupId)}
|
|
32
|
+
hideModal={noop}
|
|
33
|
+
maxHeight={text("maxHeight", null, groupId)}
|
|
34
|
+
modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
|
|
35
|
+
modalBodyText={text("modalBodyText", "Modal Body Text", groupId)}
|
|
36
|
+
modalHeaderBg={text("modalHeaderBg", "white", groupId)}
|
|
37
|
+
modalHeaderText={text("modalHeaderText", "Modal Header Text", groupId)}
|
|
38
|
+
modalOpen={boolean("modalOpen", true, groupId)}
|
|
38
39
|
noBorder={boolean("noBorder", true, groupId)}
|
|
40
|
+
noButtons={boolean("noButtons", false, groupId)}
|
|
39
41
|
onlyCloseButton={boolean("onlyCloseButton", false, groupId)}
|
|
40
42
|
onlyContinueButton={boolean("onlyContinueButton", false, groupId)}
|
|
41
|
-
|
|
42
|
-
blurUnderlay={boolean("blurUnderlay", true, groupId)}
|
|
43
|
+
useDangerButton={boolean("useDangerButton", false, groupId)}
|
|
43
44
|
/>
|
|
44
45
|
);
|
|
45
46
|
|
|
@@ -66,7 +67,7 @@ export const modalV2 = () => (
|
|
|
66
67
|
continueURL={text("continueURL", "", groupId)}
|
|
67
68
|
defaultWrapper={boolean("defaultWrapper", true, groupId)}
|
|
68
69
|
hideModal={noop}
|
|
69
|
-
maxHeight={text("maxHeight",
|
|
70
|
+
maxHeight={text("maxHeight", null, groupId)}
|
|
70
71
|
modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
|
|
71
72
|
modalBodyText={text("modalBodyText", "Modal Body Text", groupId)}
|
|
72
73
|
modalHeaderBg={text("modalHeaderBg", "white", groupId)}
|
|
@@ -121,7 +122,7 @@ export const modalWithoutButtons = () => {
|
|
|
121
122
|
modalBodyBg={text("modalBodyBg", "#F6F6F9", groupId)}
|
|
122
123
|
defaultWrapper={boolean("defaultWrapper", true, groupId)}
|
|
123
124
|
noButtons={boolean("noButtons", true, groupId)}
|
|
124
|
-
maxHeight={text("maxHeight",
|
|
125
|
+
maxHeight={text("maxHeight", null, groupId)}
|
|
125
126
|
blurUnderlay={boolean("blurUnderlay", false, groupId)}
|
|
126
127
|
/>
|
|
127
128
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Fragment, useContext, useRef } from "react";
|
|
1
|
+
import React, { Fragment, useContext, useEffect, useRef } from "react";
|
|
2
2
|
import { ThemeContext } from "styled-components";
|
|
3
3
|
import AriaModal from "react-aria-modal";
|
|
4
4
|
import { WHITE, ATHENS_GREY, SILVER_GREY } from "../../../constants/colors";
|
|
@@ -50,14 +50,27 @@ const Modal = ({
|
|
|
50
50
|
blurUnderlay = true
|
|
51
51
|
}) => {
|
|
52
52
|
const { isMobile } = useContext(ThemeContext);
|
|
53
|
-
|
|
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("[id='react-aria-modal-dialog']");
|
|
54
67
|
|
|
55
68
|
return (
|
|
56
|
-
<div ref={modalContainerRef} data-qa={dataQa}>
|
|
69
|
+
<div ref={modalContainerRef} tabIndex="-1" data-qa={dataQa}>
|
|
57
70
|
{modalOpen && (
|
|
58
71
|
<AriaModal
|
|
59
|
-
// fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
|
|
60
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
|
|
61
74
|
fallbackFocus: modalContainerRef?.current
|
|
62
75
|
}}
|
|
63
76
|
onExit={onExit}
|
|
@@ -64,7 +64,20 @@ const Modal = ({
|
|
|
64
64
|
useDangerButton = false
|
|
65
65
|
}) => {
|
|
66
66
|
const { isMobile } = useContext(ThemeContext);
|
|
67
|
-
|
|
67
|
+
|
|
68
|
+
// `AriaModal` uses `focus-trap` as a transient dependency. It automatically looks
|
|
69
|
+
// for a tabbable node when the modal mounts. When it doesn't find one, it looks to
|
|
70
|
+
// the `fallbackFocus` option. However, React does not guarantee the ref supplied to
|
|
71
|
+
// this option will be populated on initial render when `focus-trap` is checking
|
|
72
|
+
// these option. When there are no buttons in the modal, this causes an error.
|
|
73
|
+
// Because `focus-trap` cannot be disabled, the ref itself requires a default value
|
|
74
|
+
// to satisfy `focus-trap` until React populates it with the real ref value.
|
|
75
|
+
//
|
|
76
|
+
// See:
|
|
77
|
+
// - https://react.dev/reference/react/useRef#caveats
|
|
78
|
+
// - https://github.com/davidtheclark/react-aria-modal/pull/103
|
|
79
|
+
// - https://github.com/focus-trap/focus-trap?tab=readme-ov-file#createoptions
|
|
80
|
+
const modalContainerRef = useRef("[id='react-aria-modal-dialog']");
|
|
68
81
|
|
|
69
82
|
const hasCloseButton = onlyCloseButton && !noButtons;
|
|
70
83
|
const hasCancelButton = !onlyContinueButton && !onlyCloseButton && !noButtons;
|
|
@@ -72,11 +85,11 @@ const Modal = ({
|
|
|
72
85
|
(onlyContinueButton && !noButtons) || (!onlyCloseButton && !noButtons);
|
|
73
86
|
|
|
74
87
|
return (
|
|
75
|
-
<div ref={modalContainerRef} data-qa={dataQa}>
|
|
88
|
+
<div ref={modalContainerRef} tabIndex="-1" data-qa={dataQa}>
|
|
76
89
|
{modalOpen && (
|
|
77
90
|
<AriaModal
|
|
78
|
-
// fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
|
|
79
91
|
focusTrapOptions={{
|
|
92
|
+
// fallback to resolve Jest unit test errors when tabbable doesn't exist in jsdom https://github.com/focus-trap/focus-trap-react/issues/91
|
|
80
93
|
fallbackFocus: modalContainerRef?.current
|
|
81
94
|
}}
|
|
82
95
|
onExit={onExit}
|
|
@@ -143,6 +156,7 @@ const Modal = ({
|
|
|
143
156
|
cancelButtonText={cancelButtonText}
|
|
144
157
|
hideModal={hideModal}
|
|
145
158
|
isMobile={isMobile}
|
|
159
|
+
key="cancel"
|
|
146
160
|
/>
|
|
147
161
|
),
|
|
148
162
|
hasContinueButton && (
|
|
@@ -154,6 +168,7 @@ const Modal = ({
|
|
|
154
168
|
isContinueActionDisabled={isContinueActionDisabled}
|
|
155
169
|
isLoading={isLoading}
|
|
156
170
|
isMobile={isMobile}
|
|
171
|
+
key="continue"
|
|
157
172
|
useDangerButton={useDangerButton}
|
|
158
173
|
/>
|
|
159
174
|
),
|
|
@@ -163,6 +178,7 @@ const Modal = ({
|
|
|
163
178
|
closeButtonText={closeButtonText}
|
|
164
179
|
hideModal={hideModal}
|
|
165
180
|
isMobile={isMobile}
|
|
181
|
+
key="close"
|
|
166
182
|
/>
|
|
167
183
|
)
|
|
168
184
|
].filter(button => button)}
|