usePress

Handles press interactions across mouse, touch, keyboard, and screen readers. It normalizes behavior across browsers and platforms, and handles many nuances of dealing with pointer and keyboard events.

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

API#


usePress( (props: PressHookProps )): PressResult

Features#


usePress handles press interactions across mouse, touch, keyboard, and screen readers. A press interaction starts when a user presses down with a mouse or their finger on the target, and ends when they move the pointer off the target. It may start again if the pointer re-enters the target. usePress returns the current press state, which can be used to adjust the visual appearance of the target. If the pointer is released over the target, then an onPress event is fired.

  • Handles mouse and touch events
  • Handles Enter or Space key presses
  • Handles screen reader virtual clicks
  • Uses pointer events where available, with fallbacks to mouse and touch events
  • Normalizes focus behavior on mouse and touch interactions across browsers
  • Handles disabling text selection on mobile while the press interaction is active
  • Handles canceling press interactions on scroll
  • Normalizes many cross browser inconsistencies

Read our blog post about the complexities of press event handling to learn more.

Usage#


usePress returns props that you should spread onto the target element, along with the current press state:

NameTypeDescription
isPressedbooleanWhether the target is currently pressed.
pressPropsHTMLAttributes<HTMLElement>Props to spread on the target element.

usePress supports the following event handlers:

NameTypeDescription
onPress( (e: PressEvent )) => voidHandler that is called when the press is released over the target.
onPressStart( (e: PressEvent )) => voidHandler that is called when a press interaction starts.
onPressEnd( (e: PressEvent )) => voidHandler that is called when a press interaction ends, either over the target or when the pointer leaves the target.
onPressChange( (isPressed: boolean )) => voidHandler that is called when the press state changes.
onPressUp( (e: PressEvent )) => voidHandler that is called when a press is released over the target, regardless of whether it started on the target or not.

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

NameTypeDescription
type'pressstart''pressend''pressup''press'The type of 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 simple target that handles press events with usePress and logs them to a list below. It also uses the isPressed state to adjust the background color when the target is pressed. Press down on the target and drag your pointer off and over to see when the events are fired, and try focusing the target with a keyboard and pressing the Enter or Space keys to trigger events as well.

NOTE: for more advanced button functionality, see useButton.

function Example() {
  let [events, setEvents] = React.useState([]);
  let {pressProps, isPressed} = usePress({
    onPressStart: (e) =>
      setEvents((events) => [...events, `press start with ${e.pointerType}`]),
    onPressEnd: (e) =>
      setEvents((events) => [...events, `press end with ${e.pointerType}`]),
    onPress: (e) =>
      setEvents((events) => [...events, `press with ${e.pointerType}`])
  });

  return (
    <>
      <div
        {...pressProps}
        style={{
          background: isPressed ? 'darkgreen' : 'green',
          color: 'white',
          display: 'inline-block',
          padding: 4,
          cursor: 'pointer'
        }}
        role="button"
        tabIndex={0}>
        Press me!
      </div>
      <ul
        style={{
          maxHeight: '200px',
          overflow: 'auto'
        }}>
        {events.map((e, i) => (
          <li key={i}>{e}</li>
        ))}
      </ul>
    </>
  );
}
function Example() {
  let [events, setEvents] = React.useState([]);
  let {pressProps, isPressed} = usePress({
    onPressStart: (e) =>
      setEvents((events) => [
        ...events,
        `press start with ${e.pointerType}`
      ]),
    onPressEnd: (e) =>
      setEvents((events) => [
        ...events,
        `press end with ${e.pointerType}`
      ]),
    onPress: (e) =>
      setEvents((events) => [
        ...events,
        `press with ${e.pointerType}`
      ])
  });

  return (
    <>
      <div
        {...pressProps}
        style={{
          background: isPressed ? 'darkgreen' : 'green',
          color: 'white',
          display: 'inline-block',
          padding: 4,
          cursor: 'pointer'
        }}
        role="button"
        tabIndex={0}>
        Press me!
      </div>
      <ul
        style={{
          maxHeight: '200px',
          overflow: 'auto'
        }}>
        {events.map((e, i) => (
          <li key={i}>{e}</li>
        ))}
      </ul>
    </>
  );
}
function Example() {
  let [
    events,
    setEvents
  ] = React.useState([]);
  let {
    pressProps,
    isPressed
  } = usePress({
    onPressStart: (e) =>
      setEvents(
        (events) => [
          ...events,
          `press start with ${e.pointerType}`
        ]
      ),
    onPressEnd: (e) =>
      setEvents(
        (events) => [
          ...events,
          `press end with ${e.pointerType}`
        ]
      ),
    onPress: (e) =>
      setEvents(
        (events) => [
          ...events,
          `press with ${e.pointerType}`
        ]
      )
  });

  return (
    <>
      <div
        {...pressProps}
        style={{
          background: isPressed
            ? 'darkgreen'
            : 'green',
          color: 'white',
          display:
            'inline-block',
          padding: 4,
          cursor:
            'pointer'
        }}
        role="button"
        tabIndex={0}>
        Press me!
      </div>
      <ul
        style={{
          maxHeight:
            '200px',
          overflow:
            'auto'
        }}>
        {events.map(
          (e, i) => (
            <li key={i}>
              {e}
            </li>
          )
        )}
      </ul>
    </>
  );
}