use-click-outside

Detect click and touch events outside of specified element
Import

Usage

import { useState } from 'react';
import { Paper, Button } from '@mantine/core';
import { useClickOutside } from '@mantine/hooks';
export function Demo() {
const [opened, setOpened] = useState(false);
const ref = useClickOutside(() => setOpened(false));
return (
<>
<Button onClick={() => setOpened(true)}>Open dropdown</Button>
{opened && (
<Paper elementRef={ref} shadow="sm">
<span>Click outside to close</span>
</Paper>
)}
</>
);
}

API

Hook accepts 3 arguments:

  • handler – function that will be called on outside click
  • events – optional list of events that indicate outside click
  • nodes - optional list of nodes that should not trigger outside click event

Hook returns React ref object that should be passed to element on which outside clicks should be captured.

import { useClickOutside } from '@mantine/hooks';
function Example() {
const handleClickOutside = () => console.log('Clicked outside of div');
const ref = useClickOutside(handleClickOutside);
return <div ref={ref} />;
}

Change events

By default use-click-outside listens to mousedown and touchstart events, you can change these events by passing an array of events as second argument:

import { useState } from 'react';
import { Paper, Button } from '@mantine/core';
import { useClickOutside } from '@mantine/hooks';
export function Demo() {
const [opened, setOpened] = useState(false);
const ref = useClickOutside(() => setOpened(false), ['mouseup', 'touchend']);
return (
<>
<Button onClick={() => setOpened(true)}>Open dropdown</Button>
{opened && (
<Paper elementRef={ref} shadow="sm">
<span>Click outside to close</span>
</Paper>
)}
</>
);
}

Multiple nodes

In some cases you may want to trigger outside click event for multiple nodes, for example, when dropdown renders in portal. To do so provide third argument with an array of nodes which should not trigger outside click event:

// Will work only with useState, not useRef
import { useState } from 'react';
import { useClickOutside } from '@mantine/hooks';
import { Portal } from '@mantine/core';
function Demo() {
const [dropdown, setDropdown] = useState(null);
const [control, setControl] = useState(null);
useClickOutside(() => console.log('outside'), null, [control, dropdown]);
return (
// We cannot use root element ref as it does not contain dropdown
<div>
<div ref={setControl}>Control</div>
<Portal>
<div ref={setDropdown}>Dropdown</div>
</Portal>
</div>
);
}

TypeScript

Definition

function useClickOutside<T extends HTMLElement = any>(
handler: () => void,
events?: string[] | null,
nodes?: HTMLElement[]
): React.MutableRefObject<T>;

Ref type

By default use-click-outside returns ref object with React.MutableRefObject<any> type as ref type does not matter in almost all cases. You can specify ref type by passing a type:

const ref = useClickOutside<HTMLDivElement>(onClickOutside);
Build fully functional accessible web applications with ease
Feedback
Your feedback is most valuable contribution to the project, please share how you use Mantine, what features are missing and what is done good
Leave feedback