UNPKG

@mui/material

Version:

Material UI is an open-source React component library that implements Google's Material Design. It's comprehensive and can be used in production out of the box.

243 lines (188 loc) • 6.58 kB
--- productId: material-ui title: Detect click outside React component components: ClickAwayListener githubLabel: 'scope: click away listener' --- # Click-Away Listener The Click-Away Listener component detects when a click event happens outside of its child element. {{"component": "@mui/internal-core-docs/ComponentLinkHeader", "design": false}} ## Introduction Click-Away Listener is a utility component that listens for click events outside of its child. (Note that it only accepts _one_ child element.) This is useful for components like the [Popper](/material-ui/react-popper/) which should close when the user clicks anywhere else in the document. Click-Away Listener also supports the [Portal](/material-ui/react-portal/) component. The demo below shows how to hide a menu dropdown when users click anywhere else on the page: ```tsx 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 ```jsx import ClickAwayListener from '@mui/material/ClickAwayListener'; ``` ## Customization ### Use with Portal The following demo uses the [Portal](/material-ui/react-portal/) component to render the dropdown into a new subtree outside of the current DOM hierarchy: ```tsx 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> ); } ``` ### Listening for leading events By default, the Click-Away Listener component responds to **trailing events**—the _end_ of a click or touch. You can set the component to listen for **leading events** (the start of a click or touch) using the `mouseEvent` and `touchEvent` props, as shown in the following demo: :::warning When the component is set to listen for leading events, interactions with the scrollbar are ignored. ::: ```tsx 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 By default, Click-Away Listener adds an `onClick` handler to its child. This can result in screen readers announcing that the child is clickable, even though this `onClick` handler has no effect on the child itself. To prevent this behavior, add `role="presentation"` to the child element: ```tsx <ClickAwayListener> <div role="presentation"> <h1>non-interactive heading</h1> </div> </ClickAwayListener> ``` This is also required to fix a known issue in NVDA when using Firefox that prevents the announcement of alert messages—see [this GitHub issue](https://github.com/mui/material-ui/issues/29080) for details. # ClickAwayListener API ## Demos For examples and details on the usage of this React component, visit the component demo pages: - [Click-Away Listener](https://mui.com/material-ui/react-click-away-listener/) - [Menu](https://mui.com/material-ui/react-menu/) ## Import ```jsx 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 | | > **Note**: The `ref` is forwarded to the root element. ## Source code If you did not find the information on this page, consider having a look at the implementation of the component for more detail. - [/packages/mui-material/src/ClickAwayListener/ClickAwayListener.tsx](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/src/ClickAwayListener/ClickAwayListener.tsx)