Skip to content

Commit

Permalink
Trigger onClose when Dialog backdrop is clicked
Browse files Browse the repository at this point in the history
  • Loading branch information
dgreif committed May 6, 2024
1 parent e094a39 commit 94f7fa2
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
19 changes: 17 additions & 2 deletions packages/react/src/Dialog/Dialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,22 @@ describe('Dialog', () => {

await user.click(getByLabelText('Close'))

expect(onClose).toHaveBeenCalled()
expect(onClose).toHaveBeenCalledWith('close-button')
expect(onClose).toHaveBeenCalledTimes(1) // Ensure it's not called with a backdrop gesture as well
})

it('calls `onClose` when clicking the backdrop', async () => {
const user = userEvent.setup()
const onClose = jest.fn()
const {getByRole} = render(<Dialog onClose={onClose}>Pay attention to me</Dialog>)

expect(onClose).not.toHaveBeenCalled()

const dialog = getByRole('dialog')
const backdrop = dialog.parentElement!
await user.click(backdrop)

expect(onClose).toHaveBeenCalledWith('backdrop')
})

it('calls `onClose` when keying "Escape"', async () => {
Expand All @@ -80,7 +95,7 @@ describe('Dialog', () => {

await user.keyboard('{Escape}')

expect(onClose).toHaveBeenCalled()
expect(onClose).toHaveBeenCalledWith('escape')
})

it('changes the <body> style for `overflow` if it is not set to "hidden"', () => {
Expand Down
18 changes: 13 additions & 5 deletions packages/react/src/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback, useEffect, useRef, useState} from 'react'
import React, {useCallback, useEffect, useRef, useState, type SyntheticEvent} from 'react'
import styled from 'styled-components'
import type {ButtonProps} from '../Button'
import {Button} from '../Button'
Expand Down Expand Up @@ -98,11 +98,11 @@ export interface DialogProps extends SxProp {

/**
* This method is invoked when a gesture to close the dialog is used (either
* an Escape key press or clicking the "X" in the top-right corner). The
* an Escape key press, clicking the backdrop, or clicking the "X" in the top-right corner). The
* gesture argument indicates the gesture that was used to close the dialog
* (either 'close-button' or 'escape').
* ('close-button', 'backdrop', or 'escape').
*/
onClose: (gesture: 'close-button' | 'escape') => void
onClose: (gesture: 'close-button' | 'backdrop' | 'escape') => void

/**
* Default: "dialog". The ARIA role to assign to this dialog.
Expand Down Expand Up @@ -414,6 +414,14 @@ const _Dialog = React.forwardRef<HTMLDivElement, React.PropsWithChildren<DialogP
}
}
const defaultedProps = {...props, title, subtitle, role, dialogLabelId, dialogDescriptionId}
const onBackdropClick = useCallback(
(e: SyntheticEvent) => {
if (e.target === e.currentTarget) {
onClose('backdrop')
}
},
[onClose],
)

const dialogRef = useRef<HTMLDivElement>(null)
useRefObjectAsForwardedRef(forwardedRef, dialogRef)
Expand Down Expand Up @@ -465,7 +473,7 @@ const _Dialog = React.forwardRef<HTMLDivElement, React.PropsWithChildren<DialogP
return (
<>
<Portal>
<Backdrop ref={backdropRef} {...positionDataAttributes}>
<Backdrop ref={backdropRef} {...positionDataAttributes} onClick={onBackdropClick}>
<StyledDialog
width={width}
height={height}
Expand Down

0 comments on commit 94f7fa2

Please sign in to comment.