Skip to main content

useIdleDetection

Location: src/hooks/useIdleDetection.js

Overview​

Tracks user activity (mouse movement, clicks, key presses, touch, scroll, wheel) and sets an isIdle flag after a configurable period of inactivity. Activity handlers are throttled to fire at most once per second to avoid excessive state updates.

Used to support features like auto-locking, session management, and privacy-related behaviors aligned with the platform's "Privacy Is Infrastructure" invariant.

Signature​

function useIdleDetection(
timeoutMinutes?: number,
enabled?: boolean
): {
isIdle: boolean,
resetIdle: () => void,
lastActivity: number
}

Parameters​

ParameterTypeRequiredDefaultDescription
timeoutMinutesnumberNo5Minutes of inactivity before the user is considered idle.
enabledbooleanNotrueWhether idle detection is active. When false, isIdle is always false and no listeners are attached.

Return Value​

PropertyTypeDescription
isIdlebooleantrue when the user has been inactive for longer than the configured timeout. Resets to false on any user activity.
resetIdle() => voidManually reset the idle state and activity timestamp.
lastActivitynumberTimestamp (from Date.now()) of the most recent detected user activity.

Tracked Events​

The hook listens for the following events on the window object (with { passive: true }):

  • mousemove
  • mousedown
  • keydown
  • touchstart
  • scroll
  • wheel

All events are throttled to a maximum of one update per second.

Usage​

function AutoLockWrapper({ children }) {
const { isIdle } = useIdleDetection(10); // 10 minutes

if (isIdle) {
return <LockScreen />;
}

return children;
}

With custom timeout and manual reset​

function SessionManager() {
const { isIdle, resetIdle, lastActivity } = useIdleDetection(15, true);

useEffect(() => {
if (isIdle) {
showIdleWarning();
}
}, [isIdle]);

return (
<div>
<p>Last activity: {new Date(lastActivity).toLocaleTimeString()}</p>
{isIdle && (
<div>
<p>You appear to be away.</p>
<button onClick={resetIdle}>I am here</button>
</div>
)}
</div>
);
}

Last updated: 2026-02-07