Skip to content
usefy

useLongPress

Events & gestures

Long-press ("press and hold") gestures for mouse and touch — time threshold, movement cancellation, and lifecycle callbacks.

Install

$ npm install @usefy/use-long-press

Quick start

useLongPress.tsx
import { useLongPress } from "@usefy/use-long-press";

function DeleteButton() {
  const bind = useLongPress(() => deleteItem(), { threshold: 600 });

  return (
    <button {...bind} style={{ touchAction: "none", userSelect: "none" }}>
      Hold to delete
    </button>
  );
}

API reference

const bind = useLongPress(callback, options?);
// <button {...bind}>Press and hold</button>

Parameters

ParameterTypeDescription
callback(event) => voidFires once when the press reaches threshold. Receives the originating pointer-down event.
optionsUseLongPressOptionsOptional configuration (see below).

Options

OptionTypeDefaultDescription
thresholdnumber400Milliseconds the press must be held before callback fires.
moveThresholdnumber | false10Pixels the pointer may drift from the down point before cancelling (reason "moved"). false disables movement cancellation.
disabledbooleanfalseWhen true, the handlers are no-ops (read at press-start).
onStart(event) => voidFires when a valid press begins, before the timer starts.
onFinish(event) => voidFires when a completed long press is then released.
onCancel(event, { reason }) => voidFires when a press ends early — reason is "released" or "moved".

Returns

bind — a stable object of DOM handler props: onMouseDown, onMouseUp, onMouseLeave, onMouseMove, onTouchStart, onTouchEnd, onTouchMove. Spread it onto the target element to wire up the whole gesture.

preventDefault caveat

React attaches onTouchStart/onTouchMove as passive listeners, so calling event.preventDefault() inside them will not stop scrolling or the long-press context menu (the browser ignores it). Prevent those with CSS on the target instead:

.long-press-target {
  touch-action: none;      /* stop scroll/pan while pressing */
  user-select: none;       /* stop text selection */
  -webkit-touch-callout: none; /* stop the iOS callout menu */
}

This hook deliberately never calls preventDefault.

Touch / mouse de-duplication

After a touch sequence, browsers emit synthetic mousedown/mouseup/click events. useLongPress timestamps the last touch event and ignores any mousedown that arrives within a short guard window, so a single touch long-press fires exactly once. Pure-mouse and pure-touch devices are unaffected.

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 events & gestures