BACK
Use casesLong press — holding a button
Use cases · 57

Long press — holding a button

Pattern

A long press is a secondary action: show a context menu, select an element, open details. The mobile equivalent of right-click. Start a timer on pointer down, cancel it on pointer up if it's early.

The problem it solves

Imperative setTimeouts in pointer handlers quickly become a race between: an ordinary click, a long press, a context menu, and destroy. The state is hard to track, and bugs like "one tap did both actions" are very common.

Operators and why they matter

  • switchMap(() => timer(N)) — on each pointer down, create a timer. A new down cancels the previous one.
  • timer(N) — the hold duration.
  • takeUntil(pointerUp$) — release before the timer fires and the long press does NOT trigger.
  • mapTo('long-press') — success = the command.

Gotchas

  • delay without cancellation — the long press fires after an ordinary short tap.
  • exhaustMap — a second press is ignored until the first timer finishes. The user thinks the UI is unresponsive.
  • Coordinate the long press with the ordinary click. If both are registered, you need to decide whose event to apply.

What you get

The secondary action fires only on a real hold. Short taps stay ordinary clicks.

script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...