Skip to content
usefy

useIdle

Browser & device

Report user inactivity after a timeout, with throttled activity listeners.

Install

$ npm install @usefy/use-idle

Quick start

useIdle.tsx
import { useIdle } from "@usefy/use-idle";

function AwayBadge() {
  const idle = useIdle(60_000); // one minute
  return <span>{idle ? "💤 Away" : "🟢 Active"}</span>;
}

API reference

useIdle(timeout?, options?): boolean

Returns true once the user has been inactive for timeout milliseconds, and false while active. Any listened activity marks the user active and restarts the timer.

ParameterTypeDescription
timeoutnumberInactivity threshold in milliseconds before the user is considered idle. Default 60_000 (one minute).
optionsUseIdleOptionsOptional configuration (see below).

UseIdleOptions

OptionTypeDefaultDescription
eventsstring[]["mousemove", "mousedown", "resize", "keydown", "touchstart", "wheel", "visibilitychange"]Activity events that reset the idle timer. "visibilitychange" is always bound to document and handled specially.
initialStatebooleanfalseThe initial idle state (also the SSR/inert value). Set true to start idle until the first activity.
elementHTMLElement | Document | WindowwindowThe target the generic activity events attach to. "visibilitychange" is always attached to document, independent of this.

Returns: booleantrue when idle, false when active. On the server (no window) it returns initialState.

Behavior notes

  • Throttling — activity is throttled with a leading-edge guard: the idle timer is reset at most once per ~200ms (the window is clamped to the timeout if you pick a smaller one). Because that window is at most the timeout, the timer never elapses during continuous activity, but rapid mousemove/wheel/resize bursts do not re-run state work on every event.
  • Visibilityvisibilitychange is routed through a dedicated handler on document. Returning to a visible tab (document.hidden === false) counts as activity and resets the timer; backgrounding the tab is not treated as activity, so the timer keeps running and the user falls idle naturally. Remove "visibilitychange" from events to opt out.
  • Changing timeout — passing a new timeout (or events/element) tears down and restarts the listeners and timer.

Exported helpers

import {
  useIdle,
  DEFAULT_IDLE_EVENTS,   // the default activity event list
  ACTIVITY_THROTTLE_MS,  // 200 — the leading-edge throttle window
  type UseIdleOptions,
  type IdleEventTarget,  // HTMLElement | Document | Window
  type UseIdleReturn,    // boolean
} from "@usefy/use-idle";

Go deeper

This page is the quick reference. For every example, prop, and edge case, read the full README — or open Storybook to change props live.

More in browser & device