January 19, 2026

BruteJS Activity 1 - Model a drag gesture

A structured guide for capturing drag intent with explicit state transitions.

January 18, 2025·1 min read·Caleb Cannon

This guide is a structured exercise. It is meant to be followed in order.

Goal

Build a drag state machine that models intent, not pixels. The drag exists only after intent is proven.

Step 1 - Define the states

List the states as nouns. Do not list events.

  • idle
  • pressed
  • dragging
  • canceled

Step 2 - Define the events

List the inputs that move you between states.

  • pointerdown
  • pointermove
  • pointerup
  • pointercancel

Step 3 - Set the thresholds

Declare when a press becomes a drag. Do not bury this in the UI layer.

const DRAG_THRESHOLD = 6

Step 4 - Implement the transitions

Use a switch with explicit exits.

function transition(state, event) {
  if (state === 'idle' && event.type === 'pointerdown') return 'pressed'
  if (state === 'pressed' && event.type === 'pointermove' && event.delta > DRAG_THRESHOLD) {
    return 'dragging'
  }
  if (event.type === 'pointerup') return 'idle'
  if (event.type === 'pointercancel') return 'canceled'
  return state
}

Step 5 - Review the invariants

A drag means the threshold was crossed. If the UI says dragging without the threshold, you have broken the model.