Skip to content
Sapphire UIv4.1.0

Hooks and utilities

Six focused React hooks for state, browser capabilities and small interactions. Import only the hook you use. Each hook needs React as a peer.

useDebounce

Returns the initial value immediately, then waits for input to settle before updating. Useful for search queries; a new value restarts the timer.

useDebounce API
Signature
useDebounce<T>(value: T, delayMs = 300): T
import { useDebounce } from "@kongmy-dev/sapphire-ui/hooks/use-debounce";

const debouncedQuery = useDebounce(query, 300);

useMediaQuery

Subscribes to a media query. Starts false on the server and first render, then reads the browser match after mounting. Prefer CSS for layout changes.

useMediaQuery API
Signature
useMediaQuery(query: string): boolean
import { useMediaQuery } from "@kongmy-dev/sapphire-ui/hooks/use-media-query";

const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");

useLocalStorage

Uses the fallback on the server and first render, then reads storage after mounting. The required parser validates stored JSON. Invalid or unavailable storage falls back safely; storage events sync other tabs.

useLocalStorage API
Signature
useLocalStorage<T>(key: string, fallback: T, parse: (value: unknown) => T): [T, Dispatch<SetStateAction<T>>]
import { useLocalStorage } from "@kongmy-dev/sapphire-ui/hooks/use-local-storage";

const [compact, setCompact] = useLocalStorage(
  "compact", false, (value) => value === true,
);

useOnClickOutside

Listens for mouse down, touch start and focus moving outside the referenced element. Uses the composed event path for shadow DOM. Pass false or null to disable the handler.

useOnClickOutside API
Signature
useOnClickOutside<T extends HTMLElement>(ref: RefObject<T | null>, handler: ((event: MouseEvent | TouchEvent | FocusEvent) => void) | null | false): void
import { useOnClickOutside } from "@kongmy-dev/sapphire-ui/hooks/use-on-click-outside";

const panelRef = useRef<HTMLDivElement>(null);
useOnClickOutside(panelRef, open ? () => setOpen(false) : false);

useCopyToClipboard

Copies text with the browser Clipboard API. copy resolves false if access is unavailable or denied. Successful feedback resets after resetMs; use the returned boolean to report failures.

useCopyToClipboard API
Signature
useCopyToClipboard({ resetMs = 2000 } = {}): { copied: string | null; isCopied: boolean; copy(text: string): Promise<boolean> }
import { useCopyToClipboard } from "@kongmy-dev/sapphire-ui/hooks/use-copy-to-clipboard";

const { copy, isCopied } = useCopyToClipboard();
const succeeded = await copy("Hello");

useIsomorphicLayoutEffect

Uses useLayoutEffect in a browser and useEffect on the server. Reserve it for measurements that must complete before paint; return a cleanup when subscribing.

useIsomorphicLayoutEffect API
Signature
useIsomorphicLayoutEffect(effect: EffectCallback, deps?: DependencyList): void
import { useIsomorphicLayoutEffect } from "@kongmy-dev/sapphire-ui/hooks/use-isomorphic-layout-effect";

useIsomorphicLayoutEffect(() => {
  setWidth(panelRef.current?.getBoundingClientRect().width ?? 0);
}, []);

Search documentation