Skip to main content

Haptic feedback patterns

Haptic feedback only produces real vibration inside the Toss app. In a browser dev environment it logs to the console with no vibration, so you can call it unconditionally without environment guards.

useHaptic hook

import { generateHapticFeedback } from '@apps-in-toss/web-framework';
import { useCallback } from 'react';

type HapticEvent = 'tap' | 'success' | 'error' | 'celebrate';

const HAPTIC_MAP: Record<HapticEvent, Parameters<typeof generateHapticFeedback>[0]['type']> = {
tap: 'tickWeak',
success: 'success',
error: 'error',
celebrate: 'confetti',
};

export function useHaptic() {
const trigger = useCallback(async (event: HapticEvent) => {
try {
await generateHapticFeedback({ type: HAPTIC_MAP[event] });
} catch {
// vibration failure is non-fatal — ignore
}
}, []);

return trigger;
}

HapticEvent uses domain-friendly names so you don't scatter raw HapticFeedbackType strings everywhere. Adding a new event means updating HAPTIC_MAP in one place.

Suggested event mapping

SituationRecommended type
Button taptickWeak
Form submit / successsuccess
Error / validation failureerror
Level up / celebrationconfetti
Drag enter / picker changesoftMedium

Usage example

import { useHaptic } from './useHaptic';

export function SubmitButton({ onSubmit }: { onSubmit: () => Promise<void> }) {
const haptic = useHaptic();

const handleClick = async () => {
await haptic('tap');
try {
await onSubmit();
await haptic('success');
} catch {
await haptic('error');
}
};

return (
<button type="button" onClick={handleClick}>
Submit
</button>
);
}