Skip to content
dev-patterns-mobile-haptics logo

dev-patterns-mobile-haptics

Haptic feedback patterns for mobile games using Vibration API. Use when adding tactile feedback.

SKILL.md

Full skill instructions

Mobile Haptics

"Haptic feedback transforms flat screens into tactile experiences."

When to Use

Use when:

  • Building mobile/​touch controls
  • Adding game feel to actions
  • Providing feedback for UI interactions
  • Enhancing immersion on mobile devices

Quick Start

// Simple vibration feedback
function triggerHaptic(duration = 10) {
  if ('vibrate' in navigator) {
    navigator.vibrate(duration);
  }
}

// Usage
<button onClick={() => triggerHaptic(10)}>Tap</​button>

Browser Support

BrowserAndroidiOSNotes
Chrome✅ Full❌ NoFull Vibration API support
Firefox✅ Full❌ NoFull Vibration API support
Safari✅ Full❌ NoDesktop only
Edge✅ Full❌ NoChromium-based

iOS Note: iOS does NOT support the Vibration API. Use Taptic Engine feedback via native wrappers (Capacitor, React Native) for iOS.

Tap Feedback (UI Interactions)

// Light tap for button presses
function tapFeedback() {
  navigator.vibrate(10); // 10ms - very subtle
}

// Medium tap for toggle switches
function toggleFeedback() {
  navigator.vibrate(25); // 25ms - noticeable
}

// Heavy tap for confirm actions
function confirmFeedback() {
  navigator.vibrate(50); // 50ms - strong
}

Impact Patterns (Game Actions)

// Light impact - shooting, collecting items
function lightImpact() {
  navigator.vibrate(15);
}

// Medium impact - jumping, landing
function mediumImpact() {
  navigator.vibrate(30);
}

// Heavy impact - explosions, damage
function heavyImpact() {
  navigator.vibrate([50, 30, 50]); // Pattern: hit, pause, hit
}

Success Pattern

// Success - triple tap pattern
function successHaptic() {
  navigator.vibrate([10, 50, 10, 50, 10]);
}

// Level complete - ascending pattern
function levelCompleteHaptic() {
  navigator.vibrate([10, 50, 20, 50, 30]);
}

Error Pattern

// Error - double tap
function errorHaptic() {
  navigator.vibrate([50, 100, 50]);
}

// Deny - single long pulse
function denyHaptic() {
  navigator.vibrate(100);
}

Game-Specific Patterns

// Shooting feedback
function shootFeedback() {
  navigator.vibrate(15);
}

// Empty ammo click
function emptyClickFeedback() {
  navigator.vibrate([10, 30, 10]);
}

// Light damage
function lightDamageFeedback() {
  navigator.vibrate(25);
}

// Heavy damage
function heavyDamageFeedback() {
  navigator.vibrate([80, 20, 80]);
}

// Death/​respawn
function deathFeedback() {
  navigator.vibrate([100, 50, 100, 50, 200]);
}

Movement Feedback

// Footsteps - subtle, rhythmic
let stepCount = 0;
function stepFeedback() {
  // Only vibrate every 3rd step
  if (stepCount % 3 === 0) {
    navigator.vibrate(5);
  }
  stepCount++;
}

// Jump
function jumpFeedback() {
  navigator.vibrate([10, 20, 30]); // Ascending pattern
}

// Landing
function landFeedback() {
  const intensity = Math.min(fallDistance / 10, 1);
  navigator.vibrate(20 + intensity * 40);
}

Best Practices

  1. Don't overuse - Too much vibration desensitizes users
  2. Match action intensity - Heavy actions = stronger haptics
  3. Consider battery - Haptics consume battery
  4. Provide settings - Allow users to disable or adjust intensity
  5. Test on devices - Emulators don't show haptics

Reference