useOnClickOutside
Listen for clicks outside of a target element. Useful for closing modals, dropdowns, and popovers when the user clicks elsewhere.
Click outside the blue panel to close it. The counter tracks outside clicks.
import { const useRef$: { <T = any>(initialValue: null): Ref$<T | null>; <T = any>(initialValue: T): Ref$<T>; <T = any>(): Ref$<T | null>;}
useRef$ } from "@usels/core";import { const useOnClickOutside: { <T extends OnClickOutsideOptions<false>>(target: MaybeEventTarget, handler: OnClickOutsideHandler<T>, options?: T): Fn; <T extends OnClickOutsideOptions<true>>(target: MaybeEventTarget, handler: OnClickOutsideHandler<T>, options: T): OnClickOutsideReturn;}
useOnClickOutside } from "@usels/web";import { function useObservable<T>(): Observable<T | undefined> (+3 overloads)
A React hook that creates a new observable
useObservable } from "@usels/core";
function function Dropdown(): JSX.Element
Dropdown() { const const el$: Ref$<HTMLDivElement | null>
el$ = useRef$<HTMLDivElement>(): Ref$<HTMLDivElement | null> (+2 overloads)
Core (framework-agnostic) version of useRef$.
Creates an observable element ref with opaque wrapping.
- non-null value →
Ref$<T>: current, get(), peek() return T
- null / no arg →
Ref$<T | null>: current, get(), peek() return T | null
Nullability is expressed via the type parameter, mirroring T | null at the call site.
useRef$<interface HTMLDivElement
HTMLDivElement>(); const const isOpen$: any
isOpen$ = useObservable<unknown>(value: Promise<unknown> | (() => unknown) | unknown, deps?: DependencyList): any (+3 overloads)
A React hook that creates a new observable
useObservable(false);
useOnClickOutside<OnClickOutsideOptions<false>>(target: MaybeEventTarget, handler: OnClickOutsideHandler<OnClickOutsideOptions<false>>, options?: OnClickOutsideOptions<false> | undefined): Fn (+1 overload)
useOnClickOutside(const el$: Ref$<HTMLDivElement | null>
el$, () => { const isOpen$: any
isOpen$.any
set(false); });
return ( <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const isOpen$: any
isOpen$.any
set(true)}>Open</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> {const isOpen$: any
isOpen$.any
get() && <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div RefAttributes<HTMLDivElement>.ref?: Ref<HTMLDivElement> | undefined
Allows getting a ref to the component instance.
Once the component unmounts, React will set ref.current to null
(or call the ref with null if you passed a callback ref).
ref={const el$: Ref$<HTMLDivElement | null>
el$}>Dropdown content — click outside to close</JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>} </JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}import { observable, createRef$ } from "@usels/core";import { createOnClickOutside } from "@usels/web";
function Dropdown() { "use scope" const el$ = createRef$<HTMLDivElement>(); const isOpen$ = observable(false);
createOnClickOutside(el$, () => { isOpen$.set(false); });
return ( <div> <button onClick={() => isOpen$.set(true)}>Open</button> {isOpen$.get() && <div ref={el$}>Dropdown content — click outside to close</div>} </div> );}Ignore Elements
Section titled “Ignore Elements”Pass CSS selectors or element refs to the ignore option to exclude certain elements from triggering the handler.
// @noErrorsimport { useRef$ } from "@usels/core";import { useOnClickOutside } from "@usels/web";
function Component() { const el$ = useRef$<HTMLDivElement>(); const trigger$ = useRef$<HTMLButtonElement>();
useOnClickOutside( el$, () => { // won't fire when clicking the trigger button or any .ignore-me element }, { ignore: [trigger$, ".ignore-me"], } );
return ( <div> <button ref={trigger$}>Toggle</button> <div ref={el$}>Panel</div> </div> );}Iframe Detection
Section titled “Iframe Detection”Set detectIframe: true to also trigger the handler when focus moves to an iframe element outside the target.
useOnClickOutside(el$, handler, { detectIframe: true });Capture Phase
Section titled “Capture Phase”By default the event listener uses the capturing phase (capture: true).
Set capture: false to use the bubbling phase instead.
useOnClickOutside(el$, handler, { capture: false });Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
target | MaybeEventTarget | - |
handler | OnClickOutsideHandler<T> | - |
options | T | - |
OnClickOutsideOptions
Section titled “OnClickOutsideOptions”Returns
Section titled “Returns”OnClickOutsideReturn
| Name | Type | Description |
|---|---|---|
stop | Fn | Remove all event listeners |
cancel | Fn | Prevent the next outside click from triggering the handler |
trigger | (event: Event) => void | Manually trigger the handler with a given event |