From b5fa1c9d920c62f6c3ad62c99530f4484f16ba39 Mon Sep 17 00:00:00 2001 From: Puskar Adhikari Date: Mon, 18 Nov 2024 23:17:22 +0545 Subject: [PATCH] docs: use clickOutside hooks docs added --- docs/pages/_meta.json | 1 + docs/pages/useClickOutside.mdx | 90 ++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 docs/pages/useClickOutside.mdx diff --git a/docs/pages/_meta.json b/docs/pages/_meta.json index b1a63ea..3dc6a0f 100644 --- a/docs/pages/_meta.json +++ b/docs/pages/_meta.json @@ -9,6 +9,7 @@ "useArray": "useArray", "useFetch": "useFetch", "useOnScreen": "useOnScreen", + "useClickOutside": "useClickOutside", "about": { "title": "About", "type": "page" diff --git a/docs/pages/useClickOutside.mdx b/docs/pages/useClickOutside.mdx new file mode 100644 index 0000000..9fd811c --- /dev/null +++ b/docs/pages/useClickOutside.mdx @@ -0,0 +1,90 @@ +# useClickOutside + +The `useClickOutside` hook is a custom React hook designed to detect interactions outside a specified HTML element. It is particularly useful for implementing dropdowns, modals, or any UI component that requires closing or reacting to outside clicks or interactions. + +### Props + +- `handler (event: Event) => void`: The callback function that gets triggered when an interaction outside the referenced element is detected.. +- `events EventType[]` (Optional): An array of event types to listen for. Defaults to `['mousedown']`. Supported values: `"mousedown"`, `"mouseup"`, `"touchstart"`, `"touchend"`, `"focusin"`, `"focusout"` +- `listenCapturing boolean` (Optional): Indicates whether event listeners should use the capturing phase. Defaults to true. + +### Returns + +- `RefObject` A React ref object that should be attached to the target HTML element you want to monitor. + +## The Hook + +```ts filename="useClickOutside.ts" copy +import { useIsomorphicEffect } from "hooks/useIsomorphicEffect"; +import { RefObject, useRef } from "react"; + +type EventType = + | "mousedown" + | "mouseup" + | "touchstart" + | "touchend" + | "focusin" + | "focusout"; + +export function useClickOutside( + handler: (event: Event) => void, + events: EventType[] = ["mousedown"], + listenCapturing: boolean = true +): RefObject { + const ref = useRef(null); + + useIsomorphicEffect(() => { + function handleClickOutside(event: Event) { + if (typeof window === "undefined") return; + + if (ref.current && !ref.current.contains(event.target as Node)) { + handler(event); + } + } + + events.forEach((eventType) => { + document.addEventListener(eventType, handleClickOutside, listenCapturing); + }); + + return () => { + events.forEach((eventType) => { + document.removeEventListener( + eventType, + handleClickOutside, + listenCapturing + ); + }); + }; + }, [handler, events, listenCapturing]); + + return ref; +} +``` + +## Usage + +```tsx filename="UseClickOutsideDemo.tsx" copy +import React, { useState } from "react"; +import { useClickOutside } from "hooks/useClickOutside"; + +function Dropdown() { + const [isOpen, setIsOpen] = useState(false); + + const ref = useClickOutside(() => { + setIsOpen(false); // Close the dropdown when clicking outside + }); + + return ( +
+ + {isOpen && ( +
+

Dropdown Content

+
+ )} +
+ ); +} +```