useLongPress

Handles long press interactions across mouse and touch devices. Supports a customizable time threshold, accessibility description, and normalizes behavior across browsers and devices.

installyarn add @react-aria/interactions
version3.7.0
usageimport {useLongPress} from '@react-aria/interactions'

API#


useLongPress( (props: LongPressProps )): LongPressResult

Features#


useLongPress handles long press interactions across both mouse and touch devices. A long press is triggered when a user presses and holds their pointer over a target for a minimum period of time. If the user moves their pointer off of the target before the time threshold, the interaction is canceled. Once a long press event is triggered, other pointer interactions that may be active such as usePress and useMove will be canceled so that only the long press is activated.

  • Handles mouse and touch events
  • Uses pointer events where available, with fallbacks to mouse and touch events
  • Ignores emulated mouse events in mobile browsers
  • Prevents text selection on touch devices while long pressing
  • Prevents browser and OS context menus from appearing while long pressing
  • Customizable time threshold for long press
  • Supports an accessibility description to indicate to assistive technology users that a long press action is available

Usage#


useLongPress returns props that you should spread onto the target element:

NameTypeDescription
longPressPropsHTMLAttributes<HTMLElement>Props to spread on the target element.

useLongPress supports the following event handlers and options:

NameTypeDefaultDescription
isDisabledbooleanWhether long press events should be disabled.
onLongPressStart( (e: LongPressEvent )) => voidHandler that is called when a long press interaction starts.
onLongPressEnd( (e: LongPressEvent )) => voidHandler that is called when a long press interaction ends, either over the target or when the pointer leaves the target.
onLongPress( (e: LongPressEvent )) => voidHandler that is called when the threshold time is met while the press is over the target.
thresholdnumber500msThe amount of time in milliseconds to wait before triggering a long press.
accessibilityDescriptionstringA description for assistive techology users indicating that a long press action is available, e.g. "Long press to open menu".

Each of these handlers is fired with a LongPressEvent, which exposes information about the target and the type of event that triggered the interaction.

NameTypeDescription
type'longpressstart''longpressend''longpress'The type of long press event being fired.
pointerTypePointerTypeThe pointer type that triggered the press event.
targetHTMLElementThe target element of the press event.
shiftKeybooleanWhether the shift keyboard modifier was held during the press event.
ctrlKeybooleanWhether the ctrl keyboard modifier was held during the press event.
metaKeybooleanWhether the meta keyboard modifier was held during the press event.
altKeybooleanWhether the alt keyboard modifier was held during the press event.

Example#


This example shows a button that has both a normal press action using usePress, as well as a long press action using useLongPress. Pressing the button will set the mode to "Normal speed", and long pressing it will set the mode to "Hyper speed". All of the emitted events are also logged below. Note that when long pressing the button, only a long press is emitted, and no normal press is emitted on pointer up.

Note: this example does not have a keyboard accessible way to trigger the long press action. Because the method of triggering this action will differ depending on the component, it is outside the scope of useLongPress. Make sure to implement a keyboard friendly alternative to all long press interactions if you are using this hook directly.

import {mergeProps} from '@react-aria/utils';

function Example() {
  let [events, setEvents] = React.useState([]);
  let [mode, setMode] = React.useState('Activate');
  let {longPressProps} = useLongPress({
    accessibilityDescription: 'Long press to activate hyper speed',
    onLongPressStart: (e) =>
      setEvents((events) => [
        `long press start with ${e.pointerType}`,
        ...events
      ]),
    onLongPressEnd: (e) =>
      setEvents((events) => [
        `long press end with ${e.pointerType}`,
        ...events
      ]),
    onLongPress: (e) => {
      setMode('Hyper speed');
      setEvents((events) => [`long press with ${e.pointerType}`, ...events]);
    }
  });

  let {pressProps} = usePress({
    onPress: (e) => {
      setMode('Normal speed');
      setEvents((events) => [`press with ${e.pointerType}`, ...events]);
    }
  });

  return (
    <>
      <button {...mergeProps(pressProps, longPressProps)}>{mode}</button>
      <ul
        style={{
          maxHeight: '200px',
          overflow: 'auto'
        }}>
        {events.map((e, i) => (
          <li key={i}>{e}</li>
        ))}
      </ul>
    </>
  );
}
import {mergeProps} from '@react-aria/utils';

function Example() {
  let [events, setEvents] = React.useState([]);
  let [mode, setMode] = React.useState('Activate');
  let {longPressProps} = useLongPress({
    accessibilityDescription:
      'Long press to activate hyper speed',
    onLongPressStart: (e) =>
      setEvents((events) => [
        `long press start with ${e.pointerType}`,
        ...events
      ]),
    onLongPressEnd: (e) =>
      setEvents((events) => [
        `long press end with ${e.pointerType}`,
        ...events
      ]),
    onLongPress: (e) => {
      setMode('Hyper speed');
      setEvents((events) => [
        `long press with ${e.pointerType}`,
        ...events
      ]);
    }
  });

  let {pressProps} = usePress({
    onPress: (e) => {
      setMode('Normal speed');
      setEvents((events) => [
        `press with ${e.pointerType}`,
        ...events
      ]);
    }
  });

  return (
    <>
      <button {...mergeProps(pressProps, longPressProps)}>
        {mode}
      </button>
      <ul
        style={{
          maxHeight: '200px',
          overflow: 'auto'
        }}>
        {events.map((e, i) => (
          <li key={i}>{e}</li>
        ))}
      </ul>
    </>
  );
}
import {mergeProps} from '@react-aria/utils';

function Example() {
  let [
    events,
    setEvents
  ] = React.useState([]);
  let [
    mode,
    setMode
  ] = React.useState(
    'Activate'
  );
  let {
    longPressProps
  } = useLongPress({
    accessibilityDescription:
      'Long press to activate hyper speed',
    onLongPressStart: (
      e
    ) =>
      setEvents(
        (events) => [
          `long press start with ${e.pointerType}`,
          ...events
        ]
      ),
    onLongPressEnd: (
      e
    ) =>
      setEvents(
        (events) => [
          `long press end with ${e.pointerType}`,
          ...events
        ]
      ),
    onLongPress: (e) => {
      setMode(
        'Hyper speed'
      );
      setEvents(
        (events) => [
          `long press with ${e.pointerType}`,
          ...events
        ]
      );
    }
  });

  let {
    pressProps
  } = usePress({
    onPress: (e) => {
      setMode(
        'Normal speed'
      );
      setEvents(
        (events) => [
          `press with ${e.pointerType}`,
          ...events
        ]
      );
    }
  });

  return (
    <>
      <button
        {...mergeProps(
          pressProps,
          longPressProps
        )}>
        {mode}
      </button>
      <ul
        style={{
          maxHeight:
            '200px',
          overflow:
            'auto'
        }}>
        {events.map(
          (e, i) => (
            <li key={i}>
              {e}
            </li>
          )
        )}
      </ul>
    </>
  );
}