Vue utilities for Capacitor haptics with a production-ready default strategy:
- smart cooldown to prevent haptic spam
- Android softening for less aggressive feedback
- optional web fallback using
navigator.vibrate - reduced-motion support
- Vue directive, Vue plugin, and composable API
npm install vue-capacitor-haptics @capacitor/core @capacitor/hapticspnpm add vue-capacitor-haptics @capacitor/core @capacitor/hapticsyarn add vue-capacitor-haptics @capacitor/core @capacitor/hapticsimport { createApp } from 'vue';
import App from './App.vue';
import { VueCapacitorHaptics } from 'vue-capacitor-haptics';
const app = createApp(App);
app.use(VueCapacitorHaptics);
app.mount('#app');This registers the v-haptic directive globally.
import { VueCapacitorHaptics } from 'vue-capacitor-haptics';
app.use(VueCapacitorHaptics, {
directiveName: 'haptic',
defaultEvent: 'pointerdown',
defaultKind: 'tap',
engine: {
enabled: () => settingsStore.hapticsEnabled,
webVibrateFallback: true,
respectReducedMotion: true,
globalCooldownMs: 70,
repeatCooldownMs: 120,
defaultThrottleMs: 70,
},
});Recommended style: use directive arguments (v-haptic:tap, v-haptic:cta, etc.) for kind selection.
<ion-button v-haptic:tap>Tap</ion-button><ion-button v-haptic:cta>Primary CTA</ion-button>
<ion-button v-haptic:success>Success</ion-button>
<ion-button v-haptic:error>Error</ion-button><div
v-haptic="{
kind: 'selection',
event: 'pointermove',
throttle: 120,
enabled: true,
}"
/><ion-button v-haptic:success>Save</ion-button>
<ion-button v-haptic:click="{ kind: 'tap' }">Click event</ion-button>import { useHaptics } from 'vue-capacitor-haptics';
const haptics = useHaptics({
enabled: () => settingsStore.hapticsEnabled,
webVibrateFallback: true,
});
await haptics.trigger('selection');
await haptics.trigger('cta');
await haptics.trigger('success');import { useHaptics } from 'vue-capacitor-haptics';
const haptics = useHaptics();
const onStepChange = haptics.createOnChangeTrigger<number>({
kind: 'selection',
skipInitial: true,
throttle: 120,
});
await onStepChange(activeIndex.value);This is usually better than using pointermove directly, because haptics only fire when the step/value actually changes.
tap,toggle-> impact lightcta-> impact medium on iOS, softened to light on Androidselection-> selection changedsuccess,warning,error-> notification feedback
Main exports:
VueCapacitorHaptics(Vue plugin)hapticDirective,createHapticDirectiveuseHaptics,createHapticsImpactStyle,NotificationType
Main types:
HapticKindHapticEngineOptionsHapticsPluginOptionsHapticDirectiveValue,HapticDirectiveConfigTriggerHapticOptions,CreateOnChangeTriggerOptions<T>ImpactOptions,NotificationOptions,VibrateOptions
yarn type-check
yarn test
yarn test:coverage- Native haptics require a Capacitor runtime (iOS/Android).
- On web, fallback vibration is optional and browser/device dependent.
- If
prefers-reduced-motion: reduceis active andrespectReducedMotionis enabled, no haptic feedback is emitted.
MIT.