Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/ISSUE_TEMPLATE/web-haptics
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
name: Web Haptics
about: new issue
title: "[Web Haptics] <TITLE HERE>"
labels: Web Haptics
assignees: liminzhu
---
205 changes: 205 additions & 0 deletions Haptics/explainer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Web Haptics API

Authors: [Nesh Gandhe](https://github.com/neshgandhe_microsoft), [Limin Zhu](https://github.com/liminzhu)

## Status of this Document

This document is a starting point for engaging the community and standards bodies in developing collaborative solutions fit for standardization. The API is in the early ideation and interest-gauging stage, and the solution/design will likely evolve over time.

* This document status: **Active**
* Expected venue: [W3C Web Incubator Community Group](https://wicg.io/)
* Current version: **This document**

## Table of Contents
1. [Introduction](#introduction)
1. [User-Facing Problem](#user-facing-problem)
1. [Goals](#goals)
1. [Non-goals](#non-goals)
1. [Proposed Approach](#proposed-approach)
1. [Sample code](#sample-code)
1. [Alternatives Considered](#alternatives-considered)
1. [Accessibility, Internationalization, Privacy, and Security Considerations](#accessibility-internationalization-privacy-and-security-considerations)
1. [Reference for Relevant Haptics APIs](#reference-for-relevant-haptics-apis)
1. [Open Questions](#open-questions)
1. [Stakeholder Feedback / Opposition](#stakeholder-feedback--opposition)
1. [References & Acknowledgements](#references--acknowledgements)

## Introduction

Modern operating systems have embraced haptics as a core part of user experience — providing subtle, low-latency tactile cues that reinforce visual and auditory feedback. These signals improve confidence, precision, and delight in everyday interactions. The Web Haptics API proposes a semantic, cross-platform interface that connects web applications to native haptic capabilities. By focusing on intent-driven effects, the API enables web apps to deliver tactile feedback consistent with OS design principles and native experiences, while preserving and protecting user privacy and security.

An example scenario this proposal aims to support is dragging elements/windows to a snap point. This will enable a much more engaging and satisfying experience for end users.

## User-Facing Problem
The [navigator.vibrate()](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate) API exists today to allow basic or developer-defined-patterned haptics. However, it is currently mobile-centric and not supported on desktop environments. It is also coarse-grained and requires the developer to manually program the pattern.

## Goals

- Bring standardized, semantic haptic feedback to web apps across desktop and mobile platforms.
- Focus on reactive haptics feedback (i.e. haptics immediately after user input), at least for v1.
- Extensible interface for future haptics advancement on the web.
- Use intent-driven effect names rather than raw waveforms.
- Respect platform haptics user settings if available.
- Minimize privacy/fingerprinting concerns.

## Non-goals

- Guarantee identical tactile output across platforms - different platforms and user agents may choose varied output that best matches the intent.
- Cover haptics notification scenarios (e.g. vibrate to alert users when long-running task is completed), at least for v1.
- Cover/replace API for highly specialized hardware, namely gamepad.

## Proposed Approach

The Web Haptics API uses a pre-defined list of effects with an optional intensity parameter, without exposing raw waveform authoring or low-level parameters like duration, sharpness, or ramp. Developers request a named effect, and the user agent maps it to the closest native capability on the underlying OS. In order to minimize fingerprinting risks, the API does not currently allow developers to query haptics-capable hardware or available waveforms. Instead, haptics will be sent to the last input device if haptics-capable.

The current solution extends the existing `navigator.vibrate` API in order to avoid creating more haptics-related API and complicating the ecosystem. As is the case with the current API, the extended API is not gated behind permission and requires [sticky user activation](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).

```js
navigator.vibrate(pattern, {waveform: waveform; intensity: intensity});
```

The additional `options` parameter for `navigator.vibrate` accepts:
- waveform: a pre-defined set of waveform effects. Note that if `waveform` is specified and a `pattern` array is provided, `pattern` is ignored. The effects include -
- Hover: a light, subtle cue that signals something is interactive or an action may follow.
- Edge: a heavy boundary signal that indicates reaching the end of a range or hitting a limit.
- Tick: a firm, pulse that marks discrete changes, like moving through a list or slider.
- Align: a crisp confirmation when an object locks into place or aligns with guides or edges.
- Optional: a dynamic pulse that conveys motion, transitions, or intelligent system activity.
- intensity: a normalized intensity value between 0.0 and 1.0. Note that if platform intensity setting is available, then effective intensity = system intensity value * developer specified intensity. Intensity defaults to 1 if left unspecified.

There are notable limitations to this approach that are currently accepted as tradeoff for not introducing another haptics API. We may re-evaluate this based on feedback.
- The semantics of the returned boolean will need to be preserved for interop. A different design would allow for returning `true`/`false` based on whether haptics is actually triggered.
- Related to the previous point, it’s hard to do feature detection and error handling on extended options.
- A different API may also return a promise.

## Sample code
```html
<html>
<head>
<style>
#target {
width: 120px;
height: 120px;
background: #4caf50;
border-radius: 8px;
position: absolute;
top: 200px;
left: 200px;
}
#draggable {
width: 100px;
height: 100px;
background: #2196f3;
border-radius: 8px;
position: absolute;
top: 40px;
left: 40px;
cursor: grab;
touch-action: none;
}
</style>
</head>
<body>
<div id="target"></div>
<div id="draggable" draggable="true"></div>
<script>
const draggable = document.getElementById('draggable');
const target = document.getElementById('target');
let offsetX = 0, offsetY = 0;
let snapped = false;

draggable.addEventListener('pointerdown', e => {
offsetX = e.clientX - draggable.offsetLeft;
offsetY = e.clientY - draggable.offsetTop;
draggable.setPointerCapture(e.pointerId);
});

draggable.addEventListener('pointermove', e => {
if (!draggable.hasPointerCapture(e.pointerId)) return;
draggable.style.left = `${e.clientX - offsetX}px`;
draggable.style.top = `${e.clientY - offsetY}px`;
checkSnap();
});

function checkSnap() {
const dRect = draggable.getBoundingClientRect();
const tRect = target.getBoundingClientRect();
const distance = Math.hypot(
dRect.left - tRect.left,
dRect.top - tRect.top
);
const SNAP_DISTANCE = 40;
if (!snapped && distance < SNAP_DISTANCE) {
snapped = true;
// Snap the item visually
draggable.style.left = `${tRect.left}px`;
draggable.style.top = `${tRect.top}px`;
// Trigger the haptic feedback
if ("vibrate" in navigator) {
navigator.vibrate(0, {waveform: 'align', intensity: 1});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

navigator.vibrate(0, {waveform: 'align', intensity: 1});

Forcing the developer to always pass 0 for the first argument does not seem ideal. The first argument is supposed to be duration. Perhaps a better API shape would overload the existing function or create a new function to accept a single dictionary argument. I'd vote for a new function to make this feature detectable and also return a Promise<boolean> or void.

}
} else if (snapped && distance >= SNAP_DISTANCE) {
snapped = false;
}
}
</script>
</body>
</html>
```

## Alternatives considered

- A similar declarative API without re-using `navigator.vibrate`
- Pros: the new API design is not limited by existing `navigator.vibrate` design. Developer will have better feature detection and the API can also return whether haptics is played successfully and can be async.
- Cons: New interface and added ecosystem complexity.

- A pointer-event based API as previously defined in [explainer](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/HapticsDevice/explainer.md)
- Pros: Closely tie haptics to input events.
- Cons: New interface and added ecosystem complexity. Can be more cumbersome than a declarative method.

## Accessibility, Internationalization, Privacy, and Security Considerations

### Privacy
The current design does not expose means to query haptics-capable devices, available waveforms, or success in playing haptics to alleviate fingerprinting concerns.

### Security
The current design does not include permission gate for haptics but requires [sticky user activation](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation). While there is potential concern for haptics spam, this can be mitigated by user agent stopping haptics when the user navigates away and there is no lasting user impact.

## Reference for relevant haptics APIs

This section provides reference to existing web and native haptics API to help inform the API design and platform supportability.

Known platform-specific native haptics API:

- [Windows: InputHapticsManager](https://learn.microsoft.com/en-us/uwp/api/windows.devices.haptics?view=winrt-26100)
- [macOS: NSHapticFeedbackManager](https://developer.apple.com/documentation/appkit/nshapticfeedbackmanager)
- [iOS: Core Haptics](https://developer.apple.com/documentation/corehaptics)
- [Android: VibrationEffect](https://developer.android.com/reference/android/os/VibrationEffect)

Relevant web APIs:
- [navigator.vibrate](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate)
- [(In-progress) Gamepad Event-Driven Input API](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/6ea0b9190c7e8b0261323deaf060013d80a0b0ab/GamepadEventDrivenInputAPI/explainer.md)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how the "Gamepad Event-Driven Input API" relates to haptics. What did you have in mind?


## Open Questions

- Feedback on the set of predefined waveforms and how well they can be implemented on different platforms.
- How important is it for this API to inform developers whether the waveform they attempted to fire played successfully?
- If a waveform pattern isn't available on the platform, what is the correct fallback behavior (map to closest pattern, generic vibration, no vibration) and whether this should be predetermined or left for user agent discretion?
- While currently out of scope, what is the developer interest level for haptics notifications scenarios?
- What is the developer interest on haptics device enumeration and whether this can be done in a way with minimum fingerprinting concern.

## Stakeholder Feedback / Opposition

We intend to seek feedback via:

- Incubation in WICG.
- Discuss within Device & Sensors Working Group.
- Cross‑share with Haptic Industry Forum (non‑standards venue) to align on primitives vocabulary and invite suppliers/OEMs to comment publicly in WICG issues.

## References & acknowledgements

We acknowledge that this design will change and improve through input from browser vendors, standards bodies, accessibility advocates, and developers. Ongoing collaboration is essential to ensure the API meets diverse needs.

We only get here through the contributions of many—thank you to everyone who shares feedback and helps shape this work. Special thanks to:
- Ross Nichols – Contributions to Windows Haptics API design and integration guidance.
- Previous Iteration – [HapticsDevice Explainer (Microsoft Edge)](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/HapticsDevice/explainer.md), which served as the foundation for this proposal.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ These are proposals that are still really early in their lifecycle. We might jus
| [Delayed Messages API](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/DelayedMessages/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/DelayedMessages">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/DelayedMessages?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=joone&labels=DelayedMessages&title=%5BDelayedMessages%5D+%3CTITLE+HERE%3E) | Web Perf |
| [Back to Opener: Seamless Back Navigation in New Tabs](BackToOpener/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/BackToOpener">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/BackToOpener?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=victorhuangwq&labels=BackToOpener&title=%5BBackToOpener%5D+%3CTITLE+HERE%3E) | WHATWG |
| [Drag Multiple Virtual Files Out of Browser](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/DownloadURL/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/DownloadURL">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/DownloadURL?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=joone&labels=DownloadURL&title=%5BDownloadURL%5D+%3CTITLE+HERE%3E) | N/A |
| [Web Haptics](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/haptics/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/Web%20Haptics">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/Web%20Haptics?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?template=web-haptics.md) | Device |

# Alumni 🎓

Expand Down