File tree Expand file tree Collapse file tree 3 files changed +30
-2
lines changed Expand file tree Collapse file tree 3 files changed +30
-2
lines changed Original file line number Diff line number Diff line change @@ -29,6 +29,10 @@ const meta: Meta<typeof Modal> = {
29
29
disable : true ,
30
30
} ,
31
31
} ,
32
+
33
+ closeOnOutsideClick : {
34
+ control : "boolean" ,
35
+ } ,
32
36
} ,
33
37
} ;
34
38
@@ -37,7 +41,7 @@ export default meta;
37
41
type Story = StoryObj < typeof Modal > ;
38
42
39
43
export const Default : Story = {
40
- render : ( ) => {
44
+ render : ( { closeOnOutsideClick } ) => {
41
45
// eslint-disable-next-line react-hooks/rules-of-hooks
42
46
const [ modalOpen , setModalOpen ] = useState ( true ) ;
43
47
const closeHandler = ( ) => setModalOpen ( false ) ;
@@ -49,6 +53,7 @@ export const Default: Story = {
49
53
< Modal
50
54
close = { closeHandler }
51
55
title = "Confirm delete"
56
+ closeOnOutsideClick = { closeOnOutsideClick }
52
57
buttonRow = {
53
58
< >
54
59
< button className = "u-no-margin--bottom" onClick = { closeHandler } >
Original file line number Diff line number Diff line change @@ -171,4 +171,22 @@ describe("Modal ", () => {
171
171
await userEvent . click ( closeButton ! ) ;
172
172
expect ( handleExternalClick ) . toHaveBeenCalledTimes ( 1 ) ;
173
173
} ) ;
174
+
175
+ it ( "should not close modal on outside click if closeOnOutsideClick is false" , async ( ) => {
176
+ const handleCloseModal = jest . fn ( ) ;
177
+ const { container } = render (
178
+ < div >
179
+ < Modal
180
+ title = "Test"
181
+ close = { handleCloseModal }
182
+ closeOnOutsideClick = { false }
183
+ >
184
+ Bare bones
185
+ </ Modal >
186
+ </ div > ,
187
+ ) ;
188
+
189
+ await userEvent . click ( container ) ;
190
+ expect ( handleCloseModal ) . toHaveBeenCalledTimes ( 0 ) ;
191
+ } ) ;
174
192
} ) ;
Original file line number Diff line number Diff line change @@ -29,6 +29,10 @@ export type Props = PropsWithSpread<
29
29
* Whether the button click event should propagate.
30
30
*/
31
31
shouldPropagateClickEvent ?: boolean ;
32
+ /**
33
+ * Whether the modal should close when clicking outside the modal.
34
+ */
35
+ closeOnOutsideClick ?: boolean ;
32
36
} ,
33
37
HTMLProps < HTMLDivElement >
34
38
> ;
@@ -45,6 +49,7 @@ export const Modal = ({
45
49
close,
46
50
title,
47
51
shouldPropagateClickEvent = false ,
52
+ closeOnOutsideClick = true ,
48
53
...wrapperProps
49
54
} : Props ) : ReactElement => {
50
55
// list of focusable selectors is based on this Stack Overflow answer:
@@ -136,7 +141,7 @@ export const Modal = ({
136
141
const handleOverlayOnMouseDown = (
137
142
event : React . MouseEvent < HTMLDivElement > ,
138
143
) => {
139
- if ( event . target === modalRef . current ) {
144
+ if ( event . target === modalRef . current && closeOnOutsideClick ) {
140
145
shouldClose . current = true ;
141
146
}
142
147
} ;
You can’t perform that action at this time.
0 commit comments