Vitus Labs
Hooks

DOM Hooks

useElementSize, useIntersection, useClickOutside, useMergedRef, useScrollLock, useWindowResize.

useElementSize

Tracks an element's dimensions using ResizeObserver. Returns a callback ref and the current size.

import { useElementSize } from '@vitus-labs/hooks'

function ResizablePanel() {
  const [ref, { width, height }] = useElementSize()

  return (
    <div ref={ref} style={{ resize: 'both', overflow: 'auto' }}>
      Width: {width}px, Height: {height}px
    </div>
  )
}

Returns

[(node: Element | null) => void, { width: number; height: number }]

IndexTypeDescription
0Callback refAttach to the element
1{ width, height }Current dimensions (initial: { 0, 0 })

Reads initial dimensions from getBoundingClientRect() and updates via ResizeObserver.

SSR safe — gracefully returns { 0, 0 } when ResizeObserver is unavailable.


useIntersection

Observes element intersection with viewport or a root element using IntersectionObserver.

import { useIntersection } from '@vitus-labs/hooks'

function LazyImage({ src, alt }) {
  const [ref, entry] = useIntersection({ threshold: 0.1 })

  return (
    <div ref={ref}>
      {entry?.isIntersecting ? (
        <img src={src} alt={alt} />
      ) : (
        <div style={{ height: 200, background: '#eee' }} />
      )}
    </div>
  )
}

Parameters

ParameterTypeDefaultDescription
thresholdnumber | number[]0Visibility percentage (0-1)
rootMarginstring'0px'Margin around root
rootElement | nullnullRoot element (null = viewport)

Returns

[(node: Element | null) => void, IntersectionObserverEntry | null]

The entry object contains: isIntersecting, intersectionRatio, boundingClientRect, intersectionRect, rootBounds, target, time.

SSR safe — returns null entry when IntersectionObserver is unavailable.


useClickOutside

Detects clicks and touch events outside a referenced element. Useful for closing dropdowns, modals, or popovers.

import { useClickOutside } from '@vitus-labs/hooks'

function Dropdown({ onClose }) {
  const ref = useRef<HTMLDivElement>(null)
  useClickOutside(ref, onClose)

  return (
    <div ref={ref}>
      Dropdown content — clicking outside closes it
    </div>
  )
}

Parameters

ParameterTypeDescription
refRefObject<Element>Ref to the element
handler(event: Event) => voidCallback when click/touch occurs outside

Listens to both mousedown and touchstart events on document.


useMergedRef

Merges multiple refs (callback or object refs) into a single stable callback ref.

import { useMergedRef } from '@vitus-labs/hooks'
import { forwardRef, useRef } from 'react'

const Input = forwardRef((props, forwardedRef) => {
  const localRef = useRef<HTMLInputElement>(null)
  const mergedRef = useMergedRef(forwardedRef, localRef)

  return <input ref={mergedRef} {...props} />
})

Parameters

ParameterTypeDescription
...refs(Ref<T> | undefined)[]Any number of refs

Returns

(node: T | null) => void — merged callback ref.

Handles null refs gracefully. Supports mixing callback refs and object refs.


useScrollLock

Locks page scroll by setting overflow: hidden on document.body. Restores original value on disable or unmount.

import { useScrollLock } from '@vitus-labs/hooks'

function Modal({ isOpen, children }) {
  useScrollLock(isOpen)

  if (!isOpen) return null
  return <div className="modal">{children}</div>
}

Parameters

ParameterTypeDescription
enabledbooleanLock scroll when true

useWindowResize

Tracks browser viewport dimensions with configurable throttling.

import { useWindowResize } from '@vitus-labs/hooks'

function ResponsiveLayout() {
  const { width, height } = useWindowResize({ throttleDelay: 200 })

  return (
    <div>
      {width > 768 ? <DesktopLayout /> : <MobileLayout />}
      <footer>Viewport: {width} x {height}</footer>
    </div>
  )
}

Parameters

ParameterTypeDefaultDescription
params.throttleDelaynumber200Throttle delay (ms)
params.onChange({ width, height }) => voidCallback on resize
initialValues{ width?, height? }Initial values before mount

Returns

{ width: number; height: number } — current viewport dimensions.

On this page