Haptic Feedback for Vanilla JS, React, Vue, and Svelte – WebHaptics

Category: Javascript | March 5, 2026
Authorlochie
Last UpdateMarch 5, 2026
LicenseMIT
Tags
Views0 views
Haptic Feedback for Vanilla JS, React, Vue, and Svelte – WebHaptics

WebHaptics is a haptic feedback library that targets mobile browsers across React, Vue, Svelte, and vanilla JavaScript projects. It wraps the browser’s native Vibration API into a clean, framework-specific interface, exposing a trigger function that accepts preset names, raw durations, or fully custom vibration patterns.

The library ships with four built-in presets, success, nudge, error, and buzz, each mapped to a specific vibration sequence. You can pass a single number for a one-shot vibration, a number[] for an on/off alternating pattern, or a Vibration[] array with fine-grained control over duration and intensity per step.

Features:

  • Framework Hooks: Exports useWebHaptics for React and Vue, and createWebHaptics for Svelte, each scoped to their respective entry points.
  • Vanilla Class: The WebHaptics class runs outside any framework and works in plain TypeScript or JavaScript.
  • Built-in Presets: Four presets (success, nudge, error, buzz) ship with the library, each with a fixed vibration pattern and intensity.
  • Custom Patterns: The trigger method accepts a plain number, a number[] shorthand, a Vibration[] array, or a full HapticPreset object for maximum control.
  • Debug Audio Mode: A debug flag replaces vibration with audio feedback for testing haptic patterns on a desktop machine.
  • Haptic Toggle Switch: An optional UI switch lets end users turn haptic feedback on or off without extra code.
  • Cancel Support: The cancel method stops any active vibration pattern mid-execution.
  • Support Detection: The static WebHaptics.isSupported boolean checks Vibration API availability before any call runs.

Use Cases:

  • Form Validation Feedback: Trigger a short error pattern when a user submits invalid data.
  • Interactive Buttons: Provide a subtle tap response for primary actions in mobilefirst web apps.
  • Game Interactions: Use distinct buzzes for collisions, rewards, or countdowns in browserbased games.
  • Notification Alerts: Vibrate when a background process completes or a realtime event occurs.

Installation:

# NPM
$ npm install web-haptics

React

Import useWebHaptics from the React-specific entry point. The hook returns a trigger function you call inside any event handler.

import { useWebHaptics } from "web-haptics/react";
function SubmitButton() {
  const { trigger } = useWebHaptics();
  function handleClick() {
    trigger("success");
  }
  return <button onClick={handleClick}>Submit</button>;
}

Vue

Import useWebHaptics from web-haptics/vue inside a <script setup> block. Call trigger directly from a template event binding.

<script setup>
import { useWebHaptics } from "web-haptics/vue";
const { trigger } = useWebHaptics();
</script>
<template>
  <button @click="trigger('success')">Submit</button>
</template>

Svelte

The Svelte adapter exports createWebHaptics instead of a hook. Call destroy in onDestroy to clean up DOM elements and audio resources when the component unmounts.

<script>
import { createWebHaptics } from "web-haptics/svelte";
import { onDestroy } from "svelte";
const { trigger, destroy } = createWebHaptics();
onDestroy(destroy);
</script>
<button on:click={() => trigger('success')}>Submit</button>

Vanilla JavaScript / TypeScript

Instantiate WebHaptics directly for use outside a framework. Call trigger on the instance, and run destroy when the instance is no longer needed.

import { WebHaptics } from "web-haptics";
const haptics = new WebHaptics();
haptics.trigger("success");
// Clean up when done
haptics.destroy();

Custom Vibration Patterns

Beyond the built-in presets, trigger accepts four input shapes.

Single duration (number):

haptics.trigger(200); // vibrates for 200ms

Alternating on/off pattern (number[]):

haptics.trigger([100, 50, 100]); // on 100ms, off 50ms, on 100ms

Vibration array with intensity control:

haptics.trigger([
  { duration: 80, intensity: 0.8 },
  { delay: 50, duration: 100, intensity: 0.4 },
]);

Full HapticPreset object:

haptics.trigger({
  pattern: [{ duration: 50 }, { delay: 50, duration: 50 }],
  description: "double-tap",
});

Enabling Debug Mode

Pass debug: true to the constructor to hear audio feedback instead of vibration. This is useful when testing haptic patterns on a desktop browser where the Vibration API is unavailable.

const haptics = new WebHaptics({ debug: true });
haptics.trigger("error");

Showing the Haptic Toggle Switch

Pass showSwitch: true to render a UI toggle that lets users disable haptic feedback.

const haptics = new WebHaptics({ showSwitch: true });

You can also toggle both options at runtime after instantiation.

haptics.setDebug(true);
haptics.setShowSwitch(false);

Checking Device Support

Read the static isSupported property before triggering any feedback in an environment where Vibration API support is uncertain.

if (WebHaptics.isSupported) {
  haptics.trigger("nudge");
}

API Reference

Constructor

new WebHaptics(options?)

OptionTypeDefaultDescription
options.debugbooleanfalsePlays audio feedback instead of vibration for desktop testing.
options.showSwitchbooleanfalseRenders a UI toggle switch for user-controlled haptic on/off.

Methods

trigger(input?, options?): Promise<void>

Fires haptic feedback. The input argument accepts:

  • A preset name string: "success", "nudge", "error", "buzz"
  • A plain number (duration in milliseconds)
  • A number[] array (alternating on/off durations)
  • A Vibration[] array with duration, delay, and intensity per step
  • A HapticPreset object with pattern and description

The optional options.intensity value (01, default 0.5) overrides the default intensity for the triggered pattern.

cancel()

Stops the active vibration pattern immediately and cancels any pending steps.

destroy()

Removes DOM elements and frees audio resources. Call this when the instance is no longer in scope, particularly in Svelte components.

setDebug(debug: boolean)

Enables or disables audio debug mode at runtime.

setShowSwitch(show: boolean)

Shows or hides the haptic toggle switch at runtime.

Static Property

WebHaptics.isSupported

A static boolean. Returns true when the browser supports the Vibration API.

Built-in Presets

PresetPatternDescription
success[{ duration: 50 }, { delay: 50, duration: 50 }]Two short taps indicating a completed action.
nudge[{ duration: 80, intensity: 0.8 }, { delay: 80, duration: 50, intensity: 0.3 }]A strong tap followed by a lighter tap.
errorThree iterations of { duration: 50, intensity: 0.75 }Three sharp taps signaling a failure or error state.
buzz[{ duration: 1000, intensity: 1 }]A single sustained one-second vibration.

Related Resources

  • Vibration API (MDN): The browser specification that WebHaptics wraps. Read this to understand device compatibility and raw pattern syntax.

FAQs

Q: Does WebHaptics work on iOS Safari?
A: No. Apple does not implement the Vibration API in Safari or any iOS browser.

Q: Can I use a custom pattern with the React hook?
A: Yes. The trigger function returned by useWebHaptics accepts the same input types as the vanilla class, including number, number[], Vibration[], and a full HapticPreset object.

Q: When should I call destroy in Svelte vs. React?
A: In Svelte, call destroy inside onDestroy because the library creates DOM elements internally. In React, the useWebHaptics hook manages its own cleanup automatically on unmount.

Q: How do I test haptic patterns on a laptop?
A: Pass debug: true to the constructor or call setDebug(true) at runtime. The library substitutes vibration with audio cues so you can hear the timing and intensity of each step.

Q: Can I adjust intensity per vibration step?
A: Yes. Pass a Vibration[] array where each element has its own duration, optional delay, and optional intensity value between 0 and 1. The top-level options.intensity in trigger overrides the intensity for the entire pattern if set.

You Might Be Interested In:


Leave a Reply