useIdle
Browser & deviceReport user inactivity after a timeout, with throttled activity listeners.
Install
$ npm install @usefy/use-idleQuick 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.
| Parameter | Type | Description |
|---|---|---|
timeout | number | Inactivity threshold in milliseconds before the user is considered idle. Default 60_000 (one minute). |
options | UseIdleOptions | Optional configuration (see below). |
UseIdleOptions
| Option | Type | Default | Description |
|---|---|---|---|
events | string[] | ["mousemove", "mousedown", "resize", "keydown", "touchstart", "wheel", "visibilitychange"] | Activity events that reset the idle timer. "visibilitychange" is always bound to document and handled specially. |
initialState | boolean | false | The initial idle state (also the SSR/inert value). Set true to start idle until the first activity. |
element | HTMLElement | Document | Window | window | The target the generic activity events attach to. "visibilitychange" is always attached to document, independent of this. |
Returns: boolean — true 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
timeoutif you pick a smaller one). Because that window is at most the timeout, the timer never elapses during continuous activity, but rapidmousemove/wheel/resizebursts do not re-run state work on every event. - Visibility —
visibilitychangeis routed through a dedicated handler ondocument. 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"fromeventsto opt out. - Changing
timeout— passing a newtimeout(orevents/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.