Primitives to trigger and manage device vibration via the Vibration API
| Stage | Category | Version | Last Updated | Demo |
|---|---|---|---|---|
| 3 | Sensors | 1.0.0-next.2 (next) | Aug 12, 2026 | Demo → |
npm i @solid-primitives/vibrate@nextPrimitives for triggering and managing device haptic feedback via the Vibration API.
isVibrationSupported— Check if the Vibration API is available.makeVibrate— Non-reactive helper; returns[start, stop]with no Solid lifecycle dependency.createVibrate— Reactive primitive; returns{ vibrating, start, stop, supported }with automatic cleanup and reactive pattern support.frequencyToPattern— Convert a frequency in Hz to a[onMs, offMs]pattern.makePulse— Non-reactive pulse helper; vibrates continuously at a given frequency.createPulse— Reactive pulse primitive; supports reactivehzthat restarts on change.
isVibrationSupported
Returns true when the Vibration API is available. Useful for conditionally rendering haptic UI or showing fallback content.
import { isVibrationSupported } from "@solid-primitives/vibrate";
if (isVibrationSupported()) { console.log("haptics available");}makeVibrate
A non-reactive building block. Wraps navigator.vibrate with an optional repeating interval and returns [start, stop]. No Solid lifecycle dependency — both functions are no-ops when the API is unavailable.
import { makeVibrate } from "@solid-primitives/vibrate";
// Single-shot vibrationconst [start, stop] = makeVibrate([200, 100, 200]);button.addEventListener("click", start);
// Repeating vibration every 2 secondsconst [start, stop] = makeVibrate(100, { interval: 2000 });start();// later:stop();createVibrate
A reactive primitive tied to the current reactive owner. Returns { vibrating, start, stop, supported }. Cleans up automatically on owner disposal.
When pattern is a reactive accessor and changes while vibrating, vibration restarts with the new pattern automatically.
import { createVibrate } from "@solid-primitives/vibrate";import { createEffect } from "solid-js";
const { vibrating, start, stop, supported } = createVibrate([200, 100, 200]);
createEffect(() => { console.log("vibrating:", vibrating());});Reactive pattern
import { createVibrate } from "@solid-primitives/vibrate";import { createSignal } from "solid-js";
const [pattern, setPattern] = createSignal<number | number[]>(200);const { vibrating, start, stop } = createVibrate(pattern);
start();
// Changing pattern while vibrating restarts automaticallysetPattern([100, 30, 100, 30, 100]);With interval
const { vibrating, start, stop } = createVibrate(200, { interval: 1000 });start(); // repeats every secondstop(); // cancels interval + active vibrationfrequencyToPattern
Converts a frequency in Hz and an optional duty cycle into a single-cycle [onMs, offMs] vibration pattern. Useful for previewing what makePulse / createPulse will produce.
import { frequencyToPattern } from "@solid-primitives/vibrate";
frequencyToPattern(2); // [250, 250] — 2 Hz, equal on/offfrequencyToPattern(4, 0.25); // ~[63, 188] — 4 Hz, short tapmakePulse
Non-reactive pulse helper. Vibrates continuously at hz cycles per second. No Solid lifecycle dependency; both functions are no-ops when the API is unavailable.
import { makePulse } from "@solid-primitives/vibrate";
const [start, stop] = makePulse(4); // 4 taps per secondbutton.addEventListener("pointerdown", start);button.addEventListener("pointerup", stop);createPulse
Reactive pulse primitive tied to the current reactive owner. Returns { pulsing, start, stop, supported }. Accepts a reactive hz accessor — changing the frequency while pulsing restarts the vibration immediately at the new rhythm.
import { createPulse } from "@solid-primitives/vibrate";import { createSignal, createMemo } from "solid-js";
// Fixed frequencyconst { pulsing, start, stop } = createPulse(2);
// Reactive frequency — escalates as a countdown nears zeroconst [seconds, setSeconds] = createSignal(10);const hz = createMemo(() => 1 + (10 - seconds()) * 0.5);const { start, stop } = createPulse(hz);Types
export type VibratePattern = number | number[];
export interface VibrateOptions { /** Milliseconds between pattern repetitions. Omit to vibrate once per call. */ interval?: number;}
export interface PulseOptions { /** * Fraction of each cycle spent vibrating (0–1). Defaults to `0.5`. * A higher value produces longer buzzes; a lower value produces shorter taps. */ dutyCycle?: number;}Browser Support
The Vibration API is supported on Chrome/Firefox for Android. It is not supported on iOS or most desktop browsers. Always check isVibrationSupported() or rely on supported from createVibrate before enabling haptic features in your UI.
Note: vibration requires a prior user interaction (sticky activation) and may be suppressed by silent/DND mode.
Changelog
See CHANGELOG.md