@adamarant/ds-hooks
v0.1.0
Published
React hooks companion for @adamarant/designsystem — click-outside, keyboard nav, focus trap, and more.
Maintainers
Readme
@adamarant/ds-hooks
React hooks companion for @adamarant/designsystem. Optional — the CSS design system works without this package.
Install
npm install @adamarant/ds-hooksHooks
| Hook | Purpose |
|------|---------|
| useClickOutside | Close dropdowns/modals on outside click |
| useEscapeKey | Close overlays on Escape key |
| useKeyboardNav | Arrow key navigation for lists |
| useDebouncedValue | Debounce search input values |
| useFocusTrap | Trap Tab focus inside modals/drawers |
| useScrollLock | Prevent body scroll when overlay is open |
| useClipboard | Copy to clipboard with feedback state |
| useMediaQuery | Reactive CSS media query matching |
Usage
import { useClickOutside, useEscapeKey } from "@adamarant/ds-hooks";
// Or cherry-pick individual hooks
import { useClickOutside } from "@adamarant/ds-hooks/useClickOutside";useClickOutside
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, () => setOpen(false));
// Supports multiple refs: useClickOutside([ref1, ref2], handler)
// Supports enabled flag: useClickOutside(ref, handler, isOpen)useEscapeKey
useEscapeKey(() => setOpen(false), isOpen);useKeyboardNav
const { activeIndex, handleKeyDown } = useKeyboardNav({
itemCount: options.length,
onSelect: (i) => selectOption(options[i]),
onEscape: () => setOpen(false),
loop: true,
});useDebouncedValue
const [search, setSearch] = useState("");
const debouncedSearch = useDebouncedValue(search, 300);useFocusTrap
const modalRef = useRef<HTMLDivElement>(null);
useFocusTrap(modalRef, isModalOpen);useScrollLock
useScrollLock(isModalOpen);useClipboard
const { copy, copied } = useClipboard(2000);
<button onClick={() => copy(walletAddress)}>
{copied ? "Copied!" : "Copy"}
</button>useMediaQuery
const isMobile = useMediaQuery("(max-width: 767px)");
const prefersDark = useMediaQuery("(prefers-color-scheme: dark)");