useClickOutside
Call a handler when the user clicks or taps outside an element.
useClickOutside calls a handler on any mousedown or touchstart outside the referenced element. It is commonly used to close menus and popovers.
Import#
typescript
import { useClickOutside } from "@reactberry/system";
Usage#
typescript
"use client";
import { useCallback, useRef, useState } from "react";
import { useClickOutside } from "@reactberry/system";
import { Box, Button } from "@reactberry/system/elements";
export default function Dropdown() {
const [open, setOpen] = useState(false);
const ref = useRef<HTMLDivElement | null>(null);
const close = useCallback(() => setOpen(false), []);
useClickOutside(ref, close, open);
return (
<Box ref={ref} position="relative">
<Button onClick={() => setOpen((value) => !value)}>Options</Button>
{open && <Box position="absolute" p="s" skin="panel">…</Box>}
</Box>
);
}
Examples#
Turning listening on and off#
Pass enabled to attach the listeners only when needed. Toggle the switch, then click outside the card.
Listen for outside clicks
API#
typescript
function useClickOutside<T extends HTMLElement = HTMLElement>(
ref: RefObject<T | null>,
handler: (event: MouseEvent | TouchEvent) => void,
enabled?: boolean,
): void
Parameters#
| Prop | Type | Default | Description |
|---|---|---|---|
ref* | RefObject<T | null> | — | The element that counts as "inside". |
handler* | (event: MouseEvent | TouchEvent) => void | — | Called for |
enabled | boolean | true | Set |
Returns#
Nothing (void).
Accessibility#
- Only
mousedownandtouchstartare handled. Moving focus outside with the keyboard does not callhandler, so also close menus on Escape or on blur.
Notes#
- Nothing happens while
ref.currentisnull. - Listeners are re-attached whenever
handlerchanges; wrap it inuseCallback. - Events inside portalled content (rendered elsewhere in the DOM) count as outside.