v156 · web haptics · practical product use case

Snap divider

The explainer's own real-world scenario: a split-pane divider that gives an align pulse the instant it locks onto the midpoint snap guide — distance-threshold logic that CSS cannot express, which is exactly why the imperative API exists. Drag with a pointer or press the arrow keys; every attempted call lands in the log below, honestly marked as executed or skipped.

Drag the divider to the guide

navigation

The left pane. The dashed guide marks the 50% snap point — within ±2% the divider locks on and the page calls navigator.playHaptics?.("align", 0.8).

content

The right pane. Keyboard: ← → move by 1%, Shift+arrow by 5%, Home/End jump to the limits. Crossing into the snap band fires the haptic call once, like the explainer's pointermove listener.

Divider at 34%. Not snapped.

Call log (newest first)

    The pattern, from the explainer

    // Sticky activation was granted by the pointerdown that started the drag.
    divider.addEventListener('pointermove', (e) => {
      const width = e.clientX;
      if (!snapped && Math.abs(width - SNAP_POINT) < 4) {
        snapped = true;
        navigator.playHaptics?.('align', 0.8);   // optional chaining: a no-op
      } else if (snapped && Math.abs(width - SNAP_POINT) >= 4) {
        snapped = false;                          // where unsupported — never a throw
      }
    });

    see also