diff --git a/web/src/hooks/usePlatform.ts b/web/src/hooks/usePlatform.ts index 1fffb402..46fccabe 100644 --- a/web/src/hooks/usePlatform.ts +++ b/web/src/hooks/usePlatform.ts @@ -16,20 +16,51 @@ export type PlatformHaptic = { export type Platform = { /** Whether running in Telegram Mini App */ isTelegram: boolean - /** Haptic feedback (no-op on browser) */ + /** Haptic feedback (falls back to Vibration API on browser) */ haptic: PlatformHaptic } function createHaptic(): PlatformHaptic { + const tg = getTelegramWebApp() + + // Vibration patterns for web fallback (in ms) + const vibrationPatterns = { + light: 10, + medium: 20, + heavy: 30, + rigid: 15, + soft: 10, + success: 20, + warning: [20, 50, 20] as number | number[], + error: [30, 50, 30] as number | number[], + selection: 5, + } + + const vibrate = (pattern: number | number[]) => { + navigator.vibrate?.(pattern) + } + return { impact: (style: HapticStyle) => { - getTelegramWebApp()?.HapticFeedback?.impactOccurred(style) + if (tg?.HapticFeedback) { + tg.HapticFeedback.impactOccurred(style) + } else { + vibrate(vibrationPatterns[style]) + } }, notification: (type: HapticNotification) => { - getTelegramWebApp()?.HapticFeedback?.notificationOccurred(type) + if (tg?.HapticFeedback) { + tg.HapticFeedback.notificationOccurred(type) + } else { + vibrate(vibrationPatterns[type]) + } }, selection: () => { - getTelegramWebApp()?.HapticFeedback?.selectionChanged() + if (tg?.HapticFeedback) { + tg.HapticFeedback.selectionChanged() + } else { + vibrate(vibrationPatterns.selection) + } } } } diff --git a/web/tsconfig.json b/web/tsconfig.json index e631ca83..8b0682a4 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -5,7 +5,7 @@ "lib": ["ES2020", "ESNext", "ESNext.Disposable", "DOM", "DOM.Iterable"], "jsx": "react-jsx", "noEmit": true, - "types": ["vite/client", "react-syntax-highlighter"], + "types": ["vite/client"], "baseUrl": ".", "paths": { "@/*": ["./src/*"]