v156 · web haptics · canonical + migration

Semantic vs vibrate

The smallest real use of the new surface — navigator.playHaptics("tick") — side by side with the API it is designed to replace. Both buttons execute the actual call and report the actual outcome. Nothing here simulates success: the proposed API returns undefined with no success signal by design, and the legacy API's boolean return value is shown exactly as the browser produced it.

Two calls, two philosophies

proposed

navigator.playHaptics()

// intent, not milliseconds
navigator.playHaptics("tick", 0.8);
// → undefined, always.
// No success signal: content cannot
// tell whether hardware played.
Not called yet.
shipped (legacy)

navigator.vibrate()

// raw pattern: vibrate 50ms,
// pause 100ms, vibrate 50ms
const ok = navigator.vibrate([50, 100, 50]);
// → boolean. true = request accepted;
// it still plays nothing without
// vibration hardware.
Not called yet.
What actually differs
contractplayHaptics (proposed)vibrate (shipped)
you expressintent: hint / edge / tick / alignmilliseconds: [50, 100, 50]
return valueundefined — no success signal (anti-fingerprinting)boolean — request accepted or rejected
target hardwaremost recent input device (haptic touchpad, mouse, pen); never rerouteddevice vibration motor (phones); desktop silently no-ops
activation gatesticky user activation required; silently ignored without itwithout sticky activation the call returns false
policy gate"haptics" permissions policy, default selfnone (predates permissions policy)
intensity0.0–1.0, multiplied with the system settingnone — only durations

see also