Click-Away Listener
Click-Away Listener (바깥 클릭 감지)
자식 요소 바깥에서 클릭 이벤트가 발생했을 때 이를 감지해 주는 Click-Away Listener 컴포넌트에 대해 알아봅니다. 사용자가 문서의 다른 곳을 클릭하면 닫혀야 하는 Popper 같은 컴포넌트에서 특히 유용해요.
출처: 문서
본문
Click-Away Listener는 자식 요소 바깥의 클릭 이벤트를 감지하는 유틸리티 컴포넌트입니다. (자식 요소는 _하나_만 받는다는 점을 기억해 두세요.) 사용자가 문서의 아무 곳이나 클릭하면 닫혀야 하는 Popper 같은 컴포넌트에서 유용해요. Click-Away Listener는 Portal 컴포넌트도 지원합니다.
아래 데모는 사용자가 페이지의 다른 곳을 클릭하면 메뉴 드롭다운이 숨겨지는 모습을 보여줍니다.
import * as React from 'react';
import Box from '@mui/material/Box';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import { SxProps } from '@mui/system';
export default function ClickAway() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
};
const handleClickAway = () => {
setOpen(false);
};
const styles: SxProps = {
position: 'absolute',
top: 28,
right: 0,
left: 0,
zIndex: 1,
border: '1px solid',
p: 1,
bgcolor: 'background.paper',
};
return (
<ClickAwayListener onClickAway={handleClickAway}>
<Box sx={{ position: 'relative' }}>
<button type="button" onClick={handleClick}>
Open menu dropdown
</button>
{open ? (
<Box sx={styles}>
Click me, I will stay visible until you click outside.
</Box>
) : null}
</Box>
</ClickAwayListener>
);
}
기본 사용 (Basics)
Import
import ClickAwayListener from '@mui/material/ClickAwayListener';
커스터마이즈 (Customization)
Portal과 함께 사용하기
아래 데모는 Portal 컴포넌트를 사용해 드롭다운을 현재 DOM 계층 밖의 새로운 하위 트리로 렌더링합니다.
import * as React from 'react';
import Box from '@mui/material/Box';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import Portal from '@mui/material/Portal';
import { SxProps } from '@mui/system';
export default function PortalClickAway() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
};
const handleClickAway = () => {
setOpen(false);
};
const styles: SxProps = {
position: 'fixed',
width: 200,
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
border: '1px solid',
p: 1,
bgcolor: 'background.paper',
};
return (
<ClickAwayListener onClickAway={handleClickAway}>
<div>
<button type="button" onClick={handleClick}>
Open menu dropdown
</button>
{open ? (
<Portal>
<Box sx={styles}>
Click me, I will stay visible until you click outside.
</Box>
</Portal>
) : null}
</div>
</ClickAwayListener>
);
}
leading 이벤트 듣기
기본적으로 Click-Away Listener 컴포넌트는 trailing 이벤트—클릭이나 터치의 끝—에 반응합니다.
mouseEvent와 touchEvent props를 사용하면 leading 이벤트(클릭이나 터치의 시작)를 듣도록 설정할 수 있어요. 아래 데모에서 확인할 수 있습니다.
:::warning 컴포넌트가 leading 이벤트를 듣도록 설정하면 스크롤바와의 상호작용은 무시됩니다. :::
import * as React from 'react';
import Box from '@mui/material/Box';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import { SxProps } from '@mui/system';
export default function LeadingClickAway() {
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen((prev) => !prev);
};
const handleClickAway = () => {
setOpen(false);
};
const styles: SxProps = {
position: 'absolute',
top: 28,
right: 0,
left: 0,
zIndex: 1,
border: '1px solid',
p: 1,
bgcolor: 'background.paper',
};
return (
<ClickAwayListener
mouseEvent="onMouseDown"
touchEvent="onTouchStart"
onClickAway={handleClickAway}
>
<Box sx={{ position: 'relative' }}>
<button type="button" onClick={handleClick}>
Open menu dropdown
</button>
{open ? (
<Box sx={styles}>
Click me, I will stay visible until you click outside.
</Box>
) : null}
</Box>
</ClickAwayListener>
);
}
접근성 (Accessibility)
기본적으로 Click-Away Listener는 자식 요소에 onClick 핸들러를 추가합니다. 이 때문에 스크린 리더가 자식을 "클릭 가능한 요소"로 알려줄 수 있는데, 이 onClick 핸들러가 실제로 자식 요소에는 아무 효과가 없음에도 그렇죠.
이런 동작을 막으려면 자식 요소에 role="presentation"을 추가하면 됩니다.
<ClickAwayListener>
<div role="presentation">
<h1>non-interactive heading</h1>
</div>
</ClickAwayListener>
이것은 Firefox에서 NVDA를 쓸 때 경고 메시지가 발표되지 않는 알려진 문제를 고치기 위해서도 필요합니다—자세한 내용은 이 GitHub 이슈를 참고하세요.
ClickAwayListener API
Demos
이 React 컴포넌트의 사용 예시와 자세한 내용은 컴포넌트 데모 페이지에서 확인할 수 있어요.
Import
import ClickAwayListener from '@mui/material/ClickAwayListener';
// or
import { ClickAwayListener } from '@mui/material';
Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
| children | element |
- | Yes | |
| onClickAway | func |
- | Yes | |
| disableReactTree | bool |
false |
No | |
| mouseEvent | 'onClick' | 'onMouseDown' | 'onMouseUp' | 'onPointerDown' | 'onPointerUp' | false |
'onClick' |
No | |
| touchEvent | 'onTouchEnd' | 'onTouchStart' | false |
'onTouchEnd' |
No |
참고:
ref는 루트 요소.
Source code
이 페이지에서 원하는 정보를 찾지 못했다면, 더 자세한 내용은 컴포넌트 구현을 살펴보는 것도 좋아요.