Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/wellyshen/react-cool-onclickoutside
π π± React hook to listen for clicks outside of the component(s).
https://github.com/wellyshen/react-cool-onclickoutside
elements hook onclickoutside react typescript
Last synced: 4 days ago
JSON representation
π π± React hook to listen for clicks outside of the component(s).
- Host: GitHub
- URL: https://github.com/wellyshen/react-cool-onclickoutside
- Owner: wellyshen
- License: mit
- Created: 2020-01-05T14:28:07.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-08-12T16:40:16.000Z (over 1 year ago)
- Last Synced: 2024-04-22T21:14:18.596Z (8 months ago)
- Topics: elements, hook, onclickoutside, react, typescript
- Language: TypeScript
- Homepage: https://react-cool-onclickoutside.netlify.app
- Size: 6.17 MB
- Stars: 547
- Watchers: 5
- Forks: 13
- Open Issues: 30
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
- fucking-awesome-react-hooks - `react-cool-onclickoutside`
- awesome-react-hooks-cn - `react-cool-onclickoutside`
- awesome-react-hooks - `react-cool-onclickoutside`
- awesome-react-hooks - `react-cool-onclickoutside`
README
# REACT COOL ONCLICKOUTSIDE
This is a React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook) to trigger callback when user clicks outside of the target component(s) area. It's a useful logic for UI interaction design (IxD) like dismiss a dropdown menu, modal or tooltip etc. You can check the [features](#features) section to learn more.
β‘οΈ Live demo: https://react-cool-onclickoutside.netlify.app
β€οΈ it? βοΈ it on [GitHub](https://github.com/wellyshen/react-cool-onclickoutside/stargazers) or [Tweet](https://twitter.com/intent/tweet?text=With%20@react-cool-onclickoutside,%20I%20can%20build%20UI%20components%20efficiently.%20Thanks,%20@Welly%20Shen%20π€©) about it.
[![build status](https://img.shields.io/github/workflow/status/wellyshen/react-cool-onclickoutside/CI?style=flat-square)](https://github.com/wellyshen/react-cool-onclickoutside/actions?query=workflow%3ACI)
[![coverage status](https://img.shields.io/coveralls/github/wellyshen/react-cool-onclickoutside?style=flat-square)](https://coveralls.io/github/wellyshen/react-cool-onclickoutside?branch=master)
[![npm version](https://img.shields.io/npm/v/react-cool-onclickoutside?style=flat-square)](https://www.npmjs.com/package/react-cool-onclickoutside)
[![npm downloads](https://img.shields.io/npm/dm/react-cool-onclickoutside?style=flat-square)](https://www.npmtrends.com/react-cool-onclickoutside)
[![npm downloads](https://img.shields.io/npm/dt/react-cool-onclickoutside?style=flat-square)](https://www.npmtrends.com/react-cool-onclickoutside)
[![gzip size](https://badgen.net/bundlephobia/minzip/react-cool-onclickoutside?label=gzip%20size&style=flat-square)](https://bundlephobia.com/result?p=react-cool-onclickoutside)
[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange?style=flat-square)](#contributors-)
[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square)](CONTRIBUTING.md)
[![Twitter URL](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2Fwellyshen%2Freact-cool-onclickoutside)](https://twitter.com/intent/tweet?text=With%20@react-cool-onclickoutside,%20I%20can%20build%20UI%20components%20efficiently.%20Thanks,%20@Welly%20Shen%20π€©)## Features
- π£ Listens for clicks outside based on React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook).
- π―ββοΈ Supports multiple [refs](https://reactjs.org/docs/refs-and-the-dom.html) to cover more use cases.
- 𧻠Uses [passive event listeners](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners) to improve scrolling performance.
- β Scrollbar can be excluded from the callback of outside clicks.
- π [Ignores certain elements](#ignore-elements-by-css-class-name) during the event loop.
- π Enables you to [stop listening for outside clicks](#disabling-the-event-listener) when needed.
- πͺ [Detects iframe clicks](#detecting-iframe-clicks) for better DX.
- π© Supports custom `refs` for [some reasons](#use-your-own-ref).
- π Supports [TypeScript](https://www.typescriptlang.org) type definition.
- ποΈ Server-side rendering compatibility.
- π¦ Tiny size ([< 1kB gzipped](https://bundlephobia.com/result?p=react-cool-onclickoutside)). No external dependencies, aside for the `react`.## Requirement
To use `react-cool-onclickoutside`, you must use `[email protected]` or greater which includes hooks.
## Installation
This package is distributed via [npm](https://www.npmjs.com/package/react-cool-onclickoutside).
```sh
$ yarn add react-cool-onclickoutside
# or
$ npm install --save react-cool-onclickoutside
```## Usage
Common use case.
```js
import { useState } from "react";
import useOnclickOutside from "react-cool-onclickoutside";const Dropdown = () => {
const [openMenu, setOpenMenu] = useState(false);
const ref = useOnclickOutside(() => {
setOpenMenu(false);
});const handleClickBtn = () => {
setOpenMenu(!openMenu);
};return (
Button
{openMenu &&Menu}
);
};
```[![Edit useOnclickOutside demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/useonclickoutside-demo-g185l?fontsize=14&hidenavigation=1&theme=dark)
Support multiple refs. Callback only be triggered when user clicks outside of the registered components.
```js
import { useState } from "react";
import useOnclickOutside from "react-cool-onclickoutside";const App = () => {
const [showTips, setShowTips] = useState(true);
const ref = useOnclickOutside(() => {
setShowTips(false);
});return (
{showTips && (
<>
Tooltip 1
Tooltip 2
>
)}
);
};
```## Ignore Elements by CSS Class Name
You can tell `react-cool-onclickoutside` to ignore certain elements during the event loop by the `ignore-onclickoutside` CSS class name. If you want explicit control over the class name, use the `ignoreClass` option.
```js
import { useState } from "react";
import useOnclickOutside from "react-cool-onclickoutside";// Use the default CSS class name
const App = () => {
const ref = useOnclickOutside(() => {
// Do something...
});return (
I'm a π
Click me will trigger the event's callback
Click me won't trigger the event's callback
);
};// Use your own CSS class name
const App = () => {
const ref = useOnclickOutside(
() => {
// Do something...
},
{
ignoreClass: "my-ignore-class", // Or ["class-1", "class-2"]
}
);return (
I'm a π
Click me will trigger the event's callback
Click me won't trigger the event's callback
);
};
```## Disabling the Event Listener
In case you want to disable the event listener for performance reasons or fulfill some use cases. We provide the `disabled` option for you. Once you set it to `true`, the callback wonβt be triggered.
```js
import { useState } from "react";
import useOnclickOutside from "react-cool-onclickoutside";const App = () => {
const [disabled, setDisabled] = useState(false);
const ref = useOnclickOutside(
() => {
// Do something...
},
{ disabled }
);const handleBtnClick = () => {
setDisabled(true);
};return (
Stop listening for outside clicks
I'm a π
);
};
```## Use Your Own `ref`
In case of you had a ref already or you want to share a ref for other purposes. You can pass in the ref instead of using the one provided by this hook.
```js
const ref = useRef();useOnclickOutside(
() => {
// Do something...
},
{ refs: [ref] }
);
```## Detecting Iframe Clicks
Clicks on an `` element won't trigger `document.documentElement` listeners, because it's literally different page with different security domain. However, when clicking on an iframe moves `focus` to its content's window that triggers the main [window.blur](https://developer.mozilla.org/en-US/docs/Web/API/Window/blur_event) event. `react-cool-onclickoutside` in conjunction the `blur` event with [document.activeElement](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement) to detect if an iframe is clicked, and execute the provided callback.
The above-mentioned workaround has its caveats:
- Clicks on an iframe will only trigger the provided callback once. Subsequent clicks on iframe will not trigger the callback until focus has been moved back to main window.
- Move focus to iframe via keyboard navigation also triggers the provided callback.For our convenience, this feature is enabled by default. You can optionally disable it by setting the `detectIFrame` to `false` if you find it conflicting with your use-case.
## API
```js
const ref = useOnclickOutside(callback: (event: Event) => void, options?: object);
```You must register the `ref` and pass the `callback` to use this hook. Moreover you can access the `event` object via the callback's parameter, default will be [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) or [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent).
```js
const callback = (event) => {
console.log("Event: ", event);
};
```The `options` object contains the following keys.
| Key | Type | Default | Description |
| ------------------ | ------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------- |
| `refs` | Array | | For [some reasons](#use-your-own-ref), you can pass in your own `ref(s)` instead of using the built-in. |
| `disabled` | boolean | `false` | Enable/disable the event listener. |
| `eventTypes` | Array | `['mousedown', 'touchstart']` | Which events to listen for. |
| `excludeScrollbar` | boolean | `false` | Whether or not to listen (ignore) to browser scrollbar clicks. |
| `ignoreClass` | string \| string[] | `ignore-onclickoutside` | To ignore certain elements during the event loop by the CSS class name that you defined. |
| `detectIFrame` | boolean | `true` | To disable the feature of [detecting iframe clicks](#detecting-iframe-clicks). |## Articles / Blog Posts
> π‘ If you have written any blog post or article about `react-cool-onclickoutside`, please open a PR to add it here.
- Featured on [React Status #172](https://react.statuscode.com/issues/172).
## Contributors β¨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Welly
π» π π§
DmitryScaletta
π
vardani
π
Alexey Cherepanov
π»
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!