Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Base ClickAwayListener style revisions and final review #32156

Merged
merged 12 commits into from
Apr 29, 2022
Original file line number Diff line number Diff line change
@@ -1,58 +1,64 @@
---
product: base
title: Detect click outside React component
Copy link
Member

@oliviertassinari oliviertassinari Apr 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This title was on purpose for SEO. See https://stackoverflow.com/questions/32553158/detect-click-outside-react-component for why. Sure it might not be for the title but we still need to rank for this search intent:

Screenshot 2022-04-30 at 17 53 38

I have updated https://stackoverflow.com/a/59913572/2801714 to point to the latest URL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can revert this title in the final pass of the Base docs. I'll make a note of it.

title: React ClickAwayListener component
components: ClickAwayListener
githubLabel: 'component: ClickAwayListener'
packageName: '@mui/base'
---

# Click-away listener

<p class="description">Detect if a click event happened outside of an element. It listens for clicks that occur somewhere in the document.</p>
<p class="description">The <code>ClickAwayListener</code> component detects when a click event happens outside of its child element.</p>

- 📦 [981 B gzipped](/size-snapshot).
- ⚛️ Supports portals
`ClickAwayListener` is a utility component that listens for click events outside of its child.

> **Note:** the `ClickAwayListener` component only accepts _one_ child element.

This is useful for components like [`PopperUnstyled`](/base/react-popper/) which should close when the user clicks anywhere else in the document.

`ClickAwayListener` also supports the [`Portal` component](/base/react-portal/).

{{"component": "modules/components/ComponentLinkHeader.js", "design": false}}

## Example
## Basic usage

For instance, if you need to hide a menu dropdown when people click anywhere else on your page:
The following demo shows how to hide a menu dropdown when users click anywhere else on the page:

{{"demo": "ClickAway.js"}}

Notice that the component only accepts one child element.
You can find a more advanced demo on the [Menu documentation section](/material-ui/react-menu/#menulist-composition).

## Portal
mapache-salvaje marked this conversation as resolved.
Show resolved Hide resolved

The following demo uses [`Portal`](/base/react-portal/) to render the dropdown into a new "subtree" outside of current DOM hierarchy.
The following demo uses the [`Portal` component](/base/react-portal/) to render the dropdown into a new subtree outside of the current DOM hierarchy:

{{"demo": "PortalClickAway.js"}}

## Leading edge

By default, the component responds to the trailing events (click + touch end).
However, you can configure it to respond to the leading events (mouse down + touch start).
By default, the `ClickAwayListener` 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:

{{"demo": "LeadingClickAway.js"}}

> ⚠️ In this mode, only interactions on the scrollbar of the document is ignored.
> ⚠️ **Note:** when the component is set to listen for leading events, interactions with the scrollbar are ignored.

## Accessibility

By default `<ClickAwayListener />` will add an `onClick` handler to its children.
This can result in e.g. screen readers announcing the children as clickable.
However, the purpose of the `onClick` handler is not to make `children` interactive.
By default, `ClickAwayListener` will add 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.

In order to prevent screen readers from marking non-interactive children as "clickable" add `role="presentation"` to the immediate children:
To prevent this behavior, add `role="presentation"` to the child element:

```tsx
<ClickAwayListener>
<div role="presentation">
<h1>non-interactive heading</h1>
</div>
</ClickAwayListern>
</ClickAwayListener>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a general note, it can be great to search for other instances of the problem in the codebase. It's not rare to have the problem not isolated e.g. #33813 😁.

```

This is also required to fix a quirk in NVDA when using Firefox that prevents announcement of alert messages (see [mui/material-ui#29080](https://github.com/mui/material-ui/issues/29080)).
This is also required to fix a known issue in NVDA when using Firefox that prevents the announcement of alert messages—see [mui/material-ui#29080](https://github.com/mui/material-ui/issues/29080) for details.

## Bundle size

📦 [981 B gzipped](/size-snapshot).