Skip to content

Commit

Permalink
Allow Modal to keep open by adding preventHideOnOutsideClick prop…
Browse files Browse the repository at this point in the history
…erty (#1617)

<!--
  How to write a good PR title:
- Follow [the Conventional Commits
specification](https://www.conventionalcommits.org/en/v1.0.0/).
  - Give as much context as necessary and as little as possible
  - Prefix it with [WIP] while it’s a work in progress
-->

## Self Checklist

- [x] I wrote a PR title in **English** and added an appropriate
**label** to the PR.
- [x] I wrote the commit message in **English** and to follow [**the
Conventional Commits
specification**](https://www.conventionalcommits.org/en/v1.0.0/).
- [x] I [added the
**changeset**](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md)
about the changes that needed to be released. (or didn't have to)
- [x] I wrote or updated **documentation** related to the changes. (or
didn't have to)
- [x] I wrote or updated **tests** related to the changes. (or didn't
have to)
- [x] I tested the changes in various browsers. (or didn't have to)
  - Windows: Chrome, Edge, (Optional) Firefox
  - macOS: Chrome, Edge, Safari, (Optional) Firefox

## Related Issue
<!-- Please link to issue if one exists -->

<!-- Fixes #0000 -->

- Resolves #1457 

## Summary
<!-- Please brief explanation of the changes made -->

- `preventHideOnOutsideClick` 속성을 `Modal` 컴포넌트 인터페이스에 추가해서, 모달 밖을 클릭해도
모달이 닫히지 않게 할 수 있도록 합니다.

## Details
<!-- Please elaborate description of the changes -->

- radix-ui 에서 제공하는
[`Dialog.Content`](https://www.radix-ui.com/primitives/docs/components/dialog#content)
의 `onPointerDownOutside` 콜백에서 이벤트 전파를 막는 것으로 구현하였습니다.

### Breaking change? (Yes/No)
<!-- If Yes, please describe the impact and migration path for users -->

- No

## References
<!-- Please list any other resources or points the reviewer should be
aware of -->

-  #1457 
-
[`Dialog.Content`](https://www.radix-ui.com/primitives/docs/components/dialog#content)
  • Loading branch information
yangwooseong authored Sep 14, 2023
1 parent 842c80b commit 3c3a9fd
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-buckets-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@channel.io/bezier-react": minor
---

Add `preventHideOnOutsideClick` property to `Modal` component
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function ModalComposition({
description,
titleSize,
hidden,
preventHideOnOutsideClick,
}: ModalCompositionProps) {
const [show, setShow] = useState(false)

Expand All @@ -72,6 +73,7 @@ function ModalComposition({

<ModalContent
showCloseIcon={showCloseIcon}
preventHideOnOutsideClick={preventHideOnOutsideClick}
width={width}
height={height}
>
Expand Down Expand Up @@ -166,4 +168,5 @@ Composition.args = {
description: 'Make changes to your profile here. Click save when you\'re done.',
titleSize: ModalTitleSize.L,
hidden: false,
preventHideOnOutsideClick: false,
}
12 changes: 11 additions & 1 deletion packages/bezier-react/src/components/Modals/Modal/Modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,22 @@ describe('Modal', () => {
})

describe('User Interactions', () => {
it('should close the modal when the user clicks the outside of the modal', async () => {
it('should close the modal when the user clicks outside of the modal', async () => {
const { queryByRole, container } = renderOpenedModal()
await user.click(container)
expect(queryByRole('dialog')).not.toBeInTheDocument()
})

it('should keep modal open when the user clicks outside of the modal if preventHideOnOutsideClick property is true', async () => {
const { queryByRole, container } = renderOpenedModal({
modalContentProps: {
preventHideOnOutsideClick: true,
},
})
await user.click(container)
expect(queryByRole('dialog')).toBeInTheDocument()
})

it('should close the modal when the user clicks close icon button', async () => {
const { getAllByRole, queryByRole } = renderOpenedModal()
const [, closeIconButton] = getAllByRole('button')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ interface ModalContentOptions {
*/
showCloseIcon?: boolean

/**
* Decides whether modal closes when clicked outside
* @default: false
*/
preventHideOnOutsideClick?: boolean

/**
* Width of the modal.
* @default 'max-content'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const ModalContent = forwardRef(function ModalContent({
style,
container = getRootElement(),
showCloseIcon = false,
preventHideOnOutsideClick = false,
width = 'max-content',
height = 'fit-content',
zIndex = ZIndex.Modal,
Expand Down Expand Up @@ -74,7 +75,19 @@ export const ModalContent = forwardRef(function ModalContent({
return (
<DialogPrimitive.Portal container={container}>
<Styled.DialogPrimitiveOverlay style={overlayStyle}>
<DialogPrimitive.Content asChild>
<DialogPrimitive.Content
asChild
onPointerDownOutside={(e) => {
if (preventHideOnOutsideClick) {
e.preventDefault()
}
}}
onInteractOutside={(e) => {
if (preventHideOnOutsideClick) {
e.preventDefault()
}
}}
>
<Styled.Content
aria-modal
ref={contentRef}
Expand Down

0 comments on commit 3c3a9fd

Please sign in to comment.