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
Clicks outside this card: 0

API#

typescript
function useClickOutside<T extends HTMLElement = HTMLElement>(
  ref: RefObject<T | null>,
  handler: (event: MouseEvent | TouchEvent) => void,
  enabled?: boolean,
): void

Parameters#

PropTypeDefaultDescription
ref*
RefObject<T | null>
—

The element that counts as "inside".

handler*
(event: MouseEvent | TouchEvent) => void
—

Called for mousedown and touchstart events whose target is outside the element.

enabled
boolean
true

Set false to remove the listeners, for example while closed.

Returns#

Nothing (void).

Accessibility#

  • Only mousedown and touchstart are handled. Moving focus outside with the keyboard does not call handler, so also close menus on Escape or on blur.

Notes#

  • Nothing happens while ref.current is null.
  • Listeners are re-attached whenever handler changes; wrap it in useCallback.
  • Events inside portalled content (rendered elsewhere in the DOM) count as outside.