Skip to main content

React Integration

The React integration provides a useWebHaptics hook that manages the haptics instance lifecycle and provides memoized trigger functions.

Installation

1

Install the package

npm install @accede-ai/webhaptics
2

Import the hook

import { useWebHaptics } from '@accede-ai/webhaptics/react';

Basic Usage

The hook automatically initializes the WebHaptics instance on mount and cleans it up on unmount:
import { useWebHaptics } from '@accede-ai/webhaptics/react';

function App() {
  const { trigger, cancel, isSupported } = useWebHaptics();

  const handleClick = () => {
    trigger('medium');
  };

  return (
    <button onClick={handleClick}>
      Click me {!isSupported && '(haptics not supported)'}
    </button>
  );
}

API Reference

useWebHaptics(options?)

Returns an object with haptic control methods.

Parameters

options
WebHapticsOptions
Configuration options for the WebHaptics instance

Return Value

trigger
(input?: HapticInput, options?: TriggerOptions) => void
Triggers a haptic feedback pattern. Accepts:
  • A number (duration in ms)
  • A preset name string ('light', 'medium', 'heavy', 'success', etc.)
  • An array of numbers (alternating on/off durations)
  • An array of Vibration objects
  • A HapticPreset object
cancel
() => void
Cancels any currently playing haptic pattern
isSupported
boolean
Indicates whether haptic feedback is supported in the current environment

Type Definitions

interface Vibration {
  duration: number;    // Duration in milliseconds
  intensity?: number;  // 0-1, controls vibration strength (default: 0.5)
  delay?: number;      // Delay before this vibration in ms
}

type HapticInput = 
  | number              // Simple duration
  | string              // Preset name
  | number[]            // Alternating on/off pattern
  | Vibration[]         // Full control
  | HapticPreset;

interface TriggerOptions {
  intensity?: number;   // Default intensity for vibrations without explicit intensity
}

interface WebHapticsOptions {
  debug?: boolean;
  showSwitch?: boolean;
}

Examples

Form Validation Feedback

import { useWebHaptics } from '@accede-ai/webhaptics/react';
import { useState } from 'react';

function LoginForm() {
  const { trigger } = useWebHaptics();
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    
    if (!email.includes('@')) {
      setError('Invalid email');
      trigger('error');
      return;
    }
    
    setError('');
    trigger('success');
    // Submit form...
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      {error && <span className="error">{error}</span>}
      <button type="submit">Login</button>
    </form>
  );
}

Interactive Button States

import { useWebHaptics } from '@accede-ai/webhaptics/react';
import { useState } from 'react';

function ToggleButton() {
  const { trigger } = useWebHaptics({ debug: true });
  const [isActive, setIsActive] = useState(false);

  const handleToggle = () => {
    setIsActive(!isActive);
    trigger(isActive ? 'light' : 'medium');
  };

  return (
    <button
      onClick={handleToggle}
      className={isActive ? 'active' : ''}
    >
      {isActive ? 'ON' : 'OFF'}
    </button>
  );
}

Slider with Haptic Feedback

import { useWebHaptics } from '@accede-ai/webhaptics/react';
import { useState, useRef } from 'react';

function HapticSlider() {
  const { trigger } = useWebHaptics();
  const [value, setValue] = useState(50);
  const lastStepRef = useRef(5);

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newValue = parseInt(e.target.value);
    setValue(newValue);
    
    // Trigger haptic on every 10% increment
    const currentStep = Math.floor(newValue / 10);
    if (currentStep !== lastStepRef.current) {
      trigger('selection');
      lastStepRef.current = currentStep;
    }
  };

  return (
    <div>
      <input
        type="range"
        min="0"
        max="100"
        value={value}
        onChange={handleChange}
      />
      <span>{value}%</span>
    </div>
  );
}

Custom Haptic Pattern

import { useWebHaptics } from '@accede-ai/webhaptics/react';

function CustomPatternButton() {
  const { trigger } = useWebHaptics();

  const playCustomPattern = () => {
    // Create a pulsing pattern
    trigger([
      { duration: 50, intensity: 0.3 },
      { delay: 100, duration: 50, intensity: 0.6 },
      { delay: 100, duration: 50, intensity: 0.9 },
    ]);
  };

  return (
    <button onClick={playCustomPattern}>
      Play Custom Pattern
    </button>
  );
}

Common Patterns

Debug Mode for Desktop Development

Enable debug mode during development to hear audio feedback on devices without haptic support:
const { trigger } = useWebHaptics({
  debug: process.env.NODE_ENV === 'development'
});

Conditional Haptics

function NotificationBadge({ count }: { count: number }) {
  const { trigger, isSupported } = useWebHaptics();
  
  useEffect(() => {
    if (count > 0 && isSupported) {
      trigger('nudge');
    }
  }, [count, isSupported, trigger]);
  
  return count > 0 ? <span className="badge">{count}</span> : null;
}

Preventing Haptic Spam

import { useWebHaptics } from '@accede-ai/webhaptics/react';
import { useCallback, useRef } from 'react';

function useThrottledHaptic(minInterval = 100) {
  const { trigger } = useWebHaptics();
  const lastTriggerRef = useRef(0);

  return useCallback((input?: HapticInput) => {
    const now = Date.now();
    if (now - lastTriggerRef.current >= minInterval) {
      trigger(input);
      lastTriggerRef.current = now;
    }
  }, [trigger, minInterval]);
}

// Usage
function ScrollList() {
  const triggerThrottled = useThrottledHaptic(150);
  
  return (
    <div onScroll={() => triggerThrottled('selection')}>
      {/* list items */}
    </div>
  );
}

Available Presets

trigger('success')  // Ascending double-tap
trigger('warning')  // Two taps with hesitation
trigger('error')    // Three rapid harsh taps
The hook automatically manages cleanup, so you don’t need to manually destroy the WebHaptics instance. The trigger and cancel functions are stable references that won’t cause unnecessary re-renders.

Build docs developers (and LLMs) love