Web Haptics is a tiny npm package folks are sprinkling into their sites because it lets you fire haptic feedback on mobile with basically one call. Literally:
trigger
And it’s built to work across Android and iOS… with some very real caveats. The GitHub repo doesn’t overcomplicate it.Still goal is blunt: “Haptic feedback for the mobile web” and it ships helpers for React, Vue, and Svelte. Clean. Direct. Scratches a very specific itch.
Repo. Https.//github.com/lochie/web-haptics
Video discussion: https://www.youtube.com/watch?v=zAbQE6K0d1k
The quick stuff you actually need to know
Web Haptics gives you a simple trigger() API, plus helpers for React/Vue/Svelte.
A lot of “web haptics” still rides on the Vibration API when the browser/device allows it. And yeah, support is uneven. MDN straight-up labels it “not Baseline.”
You get built-in presets like "success", and you can also feed it custom vibration patterns, including intensity values.
Browsers usually require user activation to vibrate. So you need a real tap/click. Also, Silent mode / DND can block vibrations depending on the device.
If you want “real native” haptics inside an app shell, something like Tauri’s haptics plugin can be a better fit.
So what is Web Haptics, really?
Web Haptics is a small library wrapping haptic/vibration behavior behind a simple interface. The main example in the repo is almost funny how short it is:
import { useWebHaptics } from "web-haptics/react";
function App() {
const { trigger } = useWebHaptics();
return <button onClick={() => trigger}>Tap me</button>.
}That “one function and done” vibe is why it’s spreading. No hand-rolling patterns every time.Now redoing feature checks.But “wait, does iOS do this?” spirals. You just add the little tap-confirmation and move on with your day.
From the README, you also get:
- Framework hooks/helpers for React, Vue, Svelte
- A vanilla JS class via
new WebHaptics() - Options like
debugandshowSwitch - A static support check:
WebHaptics.isSupported
README: https://github.com/lochie/web-haptics/blob/main/packages/web-haptics/README.md
Where the Vibration API fits in
If you’ve ever tried “haptics on the web,” you’ve probably met navigator.vibrate()… and then immediately met the support wall.
MDN is pretty clear about the messy parts:
Navigator.vibrate()“pulses the vibration hardware” if the device supports it. If not, it does nothing.- It needs sticky user activation. Call it inside a real user gesture handler, not some random async callback later.
- If a vibration pattern is already running, a new call halts the previous pattern and starts the new one.
- Silent mode / DND can block vibration on some devices.
- It’s “not Baseline” because it “does not work in some of the most widely-used browsers.”
Docs
MDN Navigator.vibrate(). Https.//developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate
MDN Vibration API overview: https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API
So when we say Web Haptics, we’re mostly talking about a nicer developer experience sitting on top of something that’s… well, uneven. Web Haptics won’t bulldoze browser policies. But it does give you a consistent API surface and some sane defaults.
iOS Safari and Web Haptics: what we can say without hand-waving
Here’s the honest version.
- The classic Vibration API is widely associated with Android support, and iOS support has been spotty. MDN’s “not Baseline” note is the big flashing sign here.
- The Web Haptics video explicitly claims it can trigger haptics on both Android and iOS “with just one function,” and it hints there’s an “iOS trick” involved. YouTube link again. Https://www.youtube.com/watch?v=zAbQE6K0d1k
- WebKit introduced an HTML switch control in Safari 17.4:
<input type=checkbox switch>. WebKit describes it as a native-looking control that stays backward compatible, since unsupported browsers treat it like a normal checkbox.Plus post: https://webkit.org/blog/15054/an-html-switch-control/
I’m not going to pretend I know the exact internal mechanics of web-haptics beyond what the README says. But the bigger pattern is easy to see. IOS Safari keeps picking up more native-feeling UI controls, and libraries are getting clever about turning those into “web haptics” style experiences when direct vibration APIs aren’t available.
If you’re shipping something high-stakes like payments, safety alerts, or accessibility cues, test on real iPhones. Seriously. Assumptions get expensive fast.
Installing from npm
Nothing fancy here:
npm i web-haptics
# or
pnpm add web-haptics
# or
yarn add web-hapticsThe README doesn’t show any weird peer dependency drama. And the repo is TypeScript-heavy, around ~88% TypeScript, so editor hints are pretty nice.
Repo: https://github.com/lochie/web-haptics
Using Web Haptics in React, Vue, Svelte, or plain JS
This is the part where it earns its keep.
React
import { useWebHaptics } from "web-haptics/react";
export function SaveButton() {
const { trigger } = useWebHaptics();
return => {
// call inside the click handler for user activation rules
trigger.
}}
>
Save
</button>
).
}Vue
<script setup>
import { useWebHaptics } from "web-haptics/vue". Const { trigger } = useWebHaptics();
</script>
<template>
<button @click="trigger">Save</button>
</template>Svelte
<script>
import { createWebHaptics } from "web-haptics/svelte". Import { onDestroy } from "svelte";
const { trigger, destroy } = createWebHaptics();
onDestroy;
</script>
<button on:click={() => trigger}>Save</button>Vanilla JS
import { WebHaptics } from "web-haptics". Const haptics = new WebHaptics(). Document.querySelector.addEventListener => {
await haptics.trigger.
});All of those examples come straight from the README, which I appreciate. No fluff.Now “imagine a magical world where…” Just code.
Presets, patterns, intensity, and the useful little utilities
The README lists built-in patterns and explains them like a normal person. Example: “Two taps indicating success” maps to a pattern like:
[{ duration. 50 }, { delay: 50, duration: 50 }]And if you want to roll your own, you can pass patterns in a few different shapes:
// number[] shorthand (alternating on/off durations)
trigger([100, 50, 100]).
// single vibration (ms)
trigger(200);
// objects with duration/intensity and optional delay
trigger([
{ duration. 80, intensity. 0.8 },
{ delay: 50, duration: 100 }
]);
// full preset object
trigger({
pattern. [{ duration. 50 }, { delay. 50, duration: 50 }],
description: "custom",
}).There’s also an options.intensity override in the range 0–1, default 0.5.
And you get lifecycle helpers too:
cancel()stops ongoing vibrationdestroy()cleans up DOM/audio resources, which matters for SPAssetDebug(true)turns on audio feedback for desktop testing
Source: https://github.com/lochie/web-haptics/blob/main/packages/web-haptics/README.md
UX best practices so your haptics don’t become… obnoxious
Haptics are like salt. A pinch makes everything better. Dump the whole shaker and suddenly nobody wants dinner.
A few rules I stick to:
Only vibrate when something meaningful happened. Success. Error. Long-press confirmation. A drag “snap.” Stuff like that.
Keep patterns short. The presets are tiny for a reason.
Don’t spam triggers. MDN points out new vibrations cancel old ones, so rapid-fire calls can feel glitchy and weird.
Respect user preference. If you show a toggle, like showSwitch, honor it. Don’t fake it.
Accessibility matters. Some people hate haptics, and some can’t perceive them at all. Treat it as additive feedback, not the only way to understand what’s going on.
If you need a mental model, think of haptics like microcopy. It should reduce uncertainty.
Troubleshooting when “it doesn’t work”
This is my usual checklist:
Are you triggering inside a real user gesture?
MDN calls out sticky user activation fornavigator.vibrate(). Put it inside click/tap.Is the device in Silent / DND?
Some devices won’t vibrate in those modes. MDN mentions it.Does the device support it?
Web Haptics exposesWebHaptics.isSupportedand says it’s true when the device supports the Vibration API. Use it so you don’t confuse users.Are you testing on desktop?
Turn ondebugfor audio feedback. At least then you know your code path is firing.
When Web Haptics isn’t enough: Tauri haptics for app shells
If you’re building a “website in a wrapper” or an actual app, native APIs may beat browser quirks.
Tauri’s official haptics plugin supports Android and iOS and exposes functions like:
import {
vibrate,
impactFeedback,
notificationFeedback,
selectionFeedback,
} from "@tauri-apps/plugin-haptics". Await impactFeedback("medium").But notificationFeedback("warning");
await selectionFeedback();Tauri also includes a very fair warning: “There are no standards/requirements for vibration support on Android, so the feedback APIs may not work correctly on more affordable phones…” Refreshingly honest.
Docs. Https.//v2.tauri.app/plugin/haptics/
npm: https://www.npmjs.com/package/@tauri-apps/plugin-haptics?activeTab=readme
A real-world use that actually helps
I’ve used haptic taps on mobile forms where users double-submit because the UI feels laggy. A tiny “success” pulse on submit, then a sharper error pattern on validation failure, tends to reduce repeat taps. Not magic. Just… better vibes. Literally.
If you’re already tuning perceived performance with things like skeleton screens or optimistic UI, Web Haptics sits in that same bucket. Make the interface feel responsive, even when the network isn’t.
And if you’re in React land, you might like pairing this with the state/UI patterns discussed in our post on signals vs hooks: https://www.basantasapkota026.com.np/2026/03/signals-vs-hooks-what-changes-for-react.html
Should you add Web Haptics?
If your site is mobile-heavy and interaction-heavy, think shopping carts, editors, habit trackers, swipey interfaces, Web Haptics is a low-effort way to add tactile feedback without writing a pile of conditional code.
Just keep your expectations realistic. Web haptics still depends on browser capability and platform rules.
Try it in one or two places where feedback really matters. Save. Delete. Error. Ship it. Watch what people do.
Sources
- Lochie’s web-haptics GitHub repository (examples + framework support). Https.//github.com/lochie/web-haptics
- web-haptics README (API, presets, options, patterns). Https.//github.com/lochie/web-haptics/blob/main/packages/web-haptics/README.md
- YouTube. “The NPM Package Everyone Is Adding To Their Site (Web Haptics)” (claims cross-platform iOS/Android haptics, “one function”). Https.//www.youtube.com/watch?v=zAbQE6K0d1k
- Apple Podcasts listing. “The NPM Package Everyone Is Adding To Their Site (Web Haptics)” (episode metadata).
- https.//podcasts.apple.com/be/podcast/the-npm-package-everyone-is-adding-to-their-site-web-haptics/id1819342683?i=1000752908466&l=nl
- https.//podcasts.apple.com/ca/podcast/the-npm-package-everyone-is-adding-to-their-site-web-haptics/id1819342683?i=1000752908466&l=fr-CA
- MDN. Navigator.vibrate() (user activation, cancellation behavior, limitations). Https.//developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate
- MDN. Vibration API (patterns, canceling, behavior). Https.//developer.mozilla.org/en-US/docs/Web/API/Vibration_API
- WebKit Blog. An HTML Switch Control (Safari 17.4
<input type=checkbox switch>background). Https.//webkit.org/blog/15054/an-html-switch-control/ - Tauri Docs. Haptics plugin (native haptic APIs, Android caveats). Https.//v2.tauri.app/plugin/haptics/
- npm. @tauri-apps/plugin-haptics package page: https://www.npmjs.com/package/@tauri-apps/plugin-haptics?activeTab=readme