Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tijnjh/ios-haptics/llms.txt

Use this file to discover all available pages before exploring further.

iOS Safari doesn’t expose a Haptic Feedback JavaScript API. ios-haptics uses a clever DOM-based workaround to fire the Taptic Engine from the browser.

The checkbox switch trick

Safari 17.4 (iOS 17.4, March 2024) introduced <input type="checkbox" switch> — a toggle control that renders as a native switch and fires haptic feedback when clicked. ios-haptics exploits this behavior: on every haptic() call, it creates the element, clicks it to trigger the haptic, then immediately removes it from the DOM.
const labelEl = document.createElement("label");
labelEl.ariaHidden = "true";
labelEl.style.display = "none";

const inputEl = document.createElement("input");
inputEl.type = "checkbox";
inputEl.setAttribute("switch", "");
labelEl.appendChild(inputEl);

document.head.appendChild(labelEl);
labelEl.click();
document.head.removeChild(labelEl);
The label element is hidden (display: none) and marked aria-hidden="true", so it is invisible and completely inaccessible to assistive technologies.

Android fallback

On Android, navigator.vibrate() is checked first. If available, it takes priority over the checkbox trick and is used for all haptic calls.
CallVibration pattern
haptic()navigator.vibrate(50)
haptic.confirm()navigator.vibrate([50, 70, 50])
haptic.error()navigator.vibrate([50, 70, 50, 70, 50])
if (navigator.vibrate) {
  navigator.vibrate(50);
  return;
}
The array pattern for confirm and error encodes alternating vibrate/pause durations in milliseconds, producing two and three distinct pulses respectively.

Device detection

supportsHaptics uses window.matchMedia("(pointer: coarse)") to detect touchscreen devices. This returns true on phones and tablets and false on desktop browsers.
export const supportsHaptics =
  typeof window === "undefined"
    ? false
    : window.matchMedia("(pointer: coarse)").matches;
In server-side rendering (SSR) environments, window is undefined, so supportsHaptics safely returns false without throwing.

Error handling

Every haptic call is wrapped in a try/catch. If the DOM manipulation fails for any reason — for example in an environment where document.createElement behaves unexpectedly — the error is silently swallowed. Calls to haptic() will never throw.

Build docs developers (and LLMs) love