or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-expo-haptics

Provides access to the system's haptics engine on iOS, vibration effects on Android, and Web Vibration API on web.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/expo-haptics@15.0.x

To install, run

npx @tessl/cli install tessl/npm-expo-haptics@15.0.0

index.mddocs/

Expo Haptics

Expo Haptics provides access to the system's haptics engine on iOS, vibration effects on Android, and Web Vibration API on web. This library enables developers to add tactile feedback to their React Native and Expo applications across all major platforms.

Package Information

  • Package Name: expo-haptics
  • Package Type: npm
  • Language: TypeScript
  • Installation: npx expo install expo-haptics

Core Imports

import * as Haptics from 'expo-haptics';

Or import specific functions and types:

import { 
  notificationAsync, 
  impactAsync, 
  selectionAsync, 
  performAndroidHapticsAsync,
  NotificationFeedbackType,
  ImpactFeedbackStyle,
  AndroidHaptics
} from 'expo-haptics';

For CommonJS:

const Haptics = require('expo-haptics');

Basic Usage

import * as Haptics from 'expo-haptics';

// Notification feedback for system events
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);

// Impact feedback for UI interactions
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);

// Selection feedback for user selections
await Haptics.selectionAsync();

// Modern Android haptics (no VIBRATE permission required)
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Confirm);

Capabilities

Notification Feedback

Provides notification feedback for system events like success, warning, and error states. Ideal for confirming actions and alerting users to important system states.

/**
 * The kind of notification response used in the feedback.
 * @param type - A notification feedback type that on Android is simulated using Vibrator 
 * and iOS is directly mapped to UINotificationFeedbackType. You can use one of 
 * Haptics.NotificationFeedbackType.{Success, Warning, Error}. (defaults to Success)
 * @returns A Promise which fulfills once native haptics functionality is triggered
 */
function notificationAsync(type?: NotificationFeedbackType): Promise<void>;

enum NotificationFeedbackType {
  /** A notification feedback type indicating that a task has completed successfully */
  Success = 'success',
  /** A notification feedback type indicating that a task has produced a warning */
  Warning = 'warning',
  /** A notification feedback type indicating that a task has failed */
  Error = 'error'
}

Usage Examples:

import * as Haptics from 'expo-haptics';

// Success feedback
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);

// Warning feedback  
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning);

// Error feedback
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);

// Uses Success by default
await Haptics.notificationAsync();

Impact Feedback

Provides impact feedback for UI interactions, simulating collisions between user interface elements of different masses. Perfect for button taps, toggles, and other interactive elements.

/**
 * @param style - A collision indicator that on Android is simulated using Vibrator 
 * and on iOS, it is directly mapped to UIImpactFeedbackStyle. You can use one of 
 * Haptics.ImpactFeedbackStyle.{Light, Medium, Heavy, Rigid, Soft}. (defaults to Medium)
 * @returns A Promise which fulfills once native haptics functionality is triggered
 * @see Android's Vibrator API is not recommended for implementing haptics feedback. Instead, you should use
 * performAndroidHapticsAsync, which is similar to iOS haptic feedback and does not require VIBRATE permission.
 */
function impactAsync(style?: ImpactFeedbackStyle): Promise<void>;

enum ImpactFeedbackStyle {
  /** A collision between small, light user interface elements */
  Light = 'light',
  /** A collision between moderately sized user interface elements */
  Medium = 'medium',
  /** A collision between large, heavy user interface elements */
  Heavy = 'heavy',
  /** A collision between user interface elements that are soft, exhibiting a large amount of compression or elasticity */
  Soft = 'soft',
  /** A collision between user interface elements that are rigid, exhibiting a small amount of compression or elasticity */
  Rigid = 'rigid'
}

Usage Examples:

import * as Haptics from 'expo-haptics';

// Light impact for small UI elements
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);

// Medium impact (default)
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);

// Heavy impact for large UI elements
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy);

// Soft impact for elastic interactions
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Soft);

// Rigid impact for firm interactions
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Rigid);

// Uses Medium by default
await Haptics.impactAsync();

Selection Feedback

Provides selection feedback to indicate when a selection change has been registered. Ideal for pickers, sliders, and other selection-based interfaces.

/**
 * Used to let a user know when a selection change has been registered
 * @returns A Promise which fulfills once native haptics functionality is triggered
 */
function selectionAsync(): Promise<void>;

Usage Examples:

import * as Haptics from 'expo-haptics';

// Selection feedback
await Haptics.selectionAsync();

// Common use case: picker selection
const handlePickerChange = async (selectedValue: string) => {
  await Haptics.selectionAsync();
  setSelectedValue(selectedValue);
};

Android Haptics

Provides modern Android haptic feedback that doesn't require VIBRATE permission. This is the recommended approach for Android haptics as it provides better integration with the system haptics engine.

/**
 * Use the device haptics engine to provide physical feedback to the user
 * Android only - returns early on other platforms
 * @param type - The type of Android haptic effect to trigger
 * @returns Promise that resolves when haptic feedback is triggered (or immediately on non-Android platforms)
 */
function performAndroidHapticsAsync(type: AndroidHaptics): Promise<void>;

enum AndroidHaptics {
  /** A haptic effect to signal the confirmation or successful completion of a user interaction */
  Confirm = 'confirm',
  /** A haptic effect to signal the rejection or failure of a user interaction */
  Reject = 'reject',
  /** The user has started a gesture (for example, on the soft keyboard) */
  Gesture_Start = 'gesture-start',
  /** The user has finished a gesture (for example, on the soft keyboard) */
  Gesture_End = 'gesture-end',
  /** The user has toggled a switch or button into the on position */
  Toggle_On = 'toggle-on',
  /** The user has toggled a switch or button into the off position */
  Toggle_Off = 'toggle-off',
  /** The user has pressed either an hour or minute tick of a Clock */
  Clock_Tick = 'clock-tick',
  /** The user has performed a context click on an object */
  Context_Click = 'context-click',
  /** The user has started a drag-and-drop gesture. The drag target has just been "picked up" */
  Drag_Start = 'drag-start',
  /** The user has pressed a soft keyboard key */
  Keyboard_Tap = 'keyboard-tap',
  /** The user has pressed a virtual or software keyboard key */
  Keyboard_Press = 'keyboard-press',
  /** The user has released a virtual keyboard key */
  Keyboard_Release = 'keyboard-release',
  /** The user has performed a long press on an object that results in an action being performed */
  Long_Press = 'long-press',
  /** The user has pressed on a virtual on-screen key */
  Virtual_Key = 'virtual-key',
  /** The user has released a virtual key */
  Virtual_Key_Release = 'virtual-key-release',
  /** No haptic feedback should be performed */
  No_Haptics = 'no-haptics',
  /** The user is switching between a series of potential choices. For example, items in a list or discrete points on a slider */
  Segment_Tick = 'segment-tick',
  /** The user is switching between a series of many potential choices. For example, minutes on a clock face or individual percentages. This constant is expected to be very soft, so as not to be uncomfortable when performed a lot in quick succession. If the device can't make a suitably soft vibration, then it may not make any vibration */
  Segment_Frequent_Tick = 'segment-frequent-tick',
  /** The user has performed a selection/insertion handle move on text field */
  Text_Handle_Move = 'text-handle-move'
}

Usage Examples:

import * as Haptics from 'expo-haptics';

// Confirmation feedback
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Confirm);

// Rejection feedback
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Reject);

// Toggle interactions
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Toggle_On);
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Toggle_Off);

// Keyboard interactions
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Keyboard_Tap);

// Gesture feedback
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Gesture_Start);
await Haptics.performAndroidHapticsAsync(Haptics.AndroidHaptics.Gesture_End);

Platform Support

iOS

  • Implementation: Native UIFeedbackGenerator APIs
  • Support: Full support for all notification, impact, and selection feedback types
  • Permissions: No special permissions required

Android

  • Legacy Implementation: Vibrator API (requires VIBRATE permission)
  • Modern Implementation: System haptics engine via performAndroidHapticsAsync (no permissions required)
  • Recommendation: Use performAndroidHapticsAsync for better integration and no permission requirements

Web

  • Implementation: Web Vibration API with predefined vibration patterns
  • Fallback: Gracefully handles environments without vibration support
  • Patterns: Custom vibration patterns mapped to each feedback type

Error Handling

The library includes comprehensive error handling:

import * as Haptics from 'expo-haptics';

try {
  await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
} catch (error) {
  // Handles UnavailabilityError when haptics is not supported
  console.log('Haptics not available on this device');
}

Common Error Conditions:

  • UnavailabilityError: Thrown when native haptics functionality is unavailable
    • notificationAsync: Throws UnavailabilityError('Haptics', 'notificationAsync')
    • impactAsync: Throws UnavailabilityError('Haptic', 'impactAsync')
    • selectionAsync: Throws UnavailabilityError('Haptic', 'selectionAsync')
  • Platform Limitations: performAndroidHapticsAsync returns early on non-Android platforms
  • Web Environment: Web implementation gracefully handles missing vibration support

Installation Requirements

Expo Managed Projects

npx expo install expo-haptics

Bare React Native Projects

  1. Install the package: npx expo install expo-haptics
  2. Configure for iOS: Run npx pod-install
  3. Android: No additional configuration required

Android Permissions: The legacy Vibrator API automatically adds the VIBRATE permission:

<uses-permission android:name="android.permission.VIBRATE" />

Note: performAndroidHapticsAsync does not require this permission and is the recommended approach for Android.