v156 · capabilities (fugu) · proposed
Web haptics JavaScript API
The legacy navigator.vibrate() makes you program raw millisecond patterns — a mobile-centric model that maps badly onto haptic touchpads, pens and mice. The proposed navigator.playHaptics(effect, intensity) flips the contract: you name the intent — hint, edge, tick, align — and the user agent picks the platform waveform. It returns undefined on purpose: no success signal means no new fingerprinting surface.
concepts
-
Semantic vs vibrate
The canonical call next to the API it replaces. One button attempts the real
navigator.playHaptics("tick")and reports exactly what came back; the other drives the real, shippednavigator.vibrate()and surfaces its actual boolean return value — on a desktop with no vibration hardware, that return value is itself the honest observable. -
Effect design tool
Pick a semantic effect and an intensity; read the exact proposed call, the platform waveform each OS maps it to, and a visual, audio-free timeline sketch of the pulse with text equivalents. Includes the hand-tuned
vibrate()pattern a developer would ship today — playable for real where vibration hardware exists. -
Snap divider
The explainer's own product scenario: a draggable split-pane divider that calls
navigator.playHaptics?.("align", 0.8)the instant it locks onto the snap point. Drag it with pointer or arrow keys; the call log records every real attempt and says plainly when the API is absent and the call was skipped. -
Activation & policy gates
The edge and failure model: the four gates every call passes — fenced frame, the
"haptics"permissions policy (default allowlistself), sticky user activation, intensity clamping. Live readouts ofnavigator.userActivationand the real permissions-policy feature list, plus what the bindings do withNaNand out-of-range intensity.
why it shipped
It hasn't yet — Chrome lists it as Proposed (an early-stage Fugu capability driven by Microsoft, incubated in WICG). The motivation is the gap between how designers think about haptics ("a tick when the carousel snaps") and what navigator.vibrate() offers (hand-tuned duration arrays that feel different on every device, and nothing at all on desktops with haptic touchpads). A semantic vocabulary lets the OS map intent to its own primitives — Windows waveforms, Core Haptics, VibrationEffect — and lets the same code feel native everywhere. The first implementation targets Windows 11 24H2+ input devices; the companion declarative CSS @haptic at-rule is still design-TBD.
research record — use cases & exact surface
- Exact surface (Chromium design doc, Aug 2026):
partial interface Navigator { undefined playHaptics(HapticEffect effect, optional double intensity = 1); }withenum HapticEffect { "hint", "edge", "tick", "align" }. Returnsundefined, exposes no success signal. The WICG explainer's vocabulary additionally proposessuccessanderroroutcome effects, not yet in the Chromium IDL — the demos mark those two as explainer-level. - Gating (design doc D2/D4): fenced-frame suppression →
"haptics"permissions policy (default allowlistself, registered withdepends_on: ["WebHaptics"]) → sticky user activation → intensity clamped to [0,1], non-finite rejected. Every early return is silent. - Runtime flag:
WebHaptics, statusexperimentalinruntime_enabled_features.json5(verified on trunk) — enable with--enable-blink-features=WebHapticsor--enable-experimental-web-platform-features. No dedicatedchrome://flagsentry at the time of writing. Finch nameWebHaptics. - Hardware/OS floor: the first backend is Windows-only via
Windows.Devices.Haptics.InputHapticsManager(UniversalApiContract 19.0 → Windows 11 24H2+); mapping hint→Hover, edge→Collide, tick→Step, align→Align, with a device-type default fallback (mouse/touchpad→Hover, pen→Click). Target model: the most recent input device, never rerouted. - Use-case portfolio: canonical call + migration comparison (semantic-vs-vibrate), configuration/inspection (effect-design-tool), the explainer's practical drag-to-snap divider (snap-divider), and the gating/edge model (activation-and-policy-gates). The novel-composition angle — the declarative CSS
@hapticat-rule — is not built as a live demo because the design doc marks the entire CSS surface "Design TBD" with no parseable syntax in any build; it is explained inside the design tool instead and should become its own concept once a grammar lands.