WIP PWA for Grain
next.grain.social
1/**
2 * Haptic feedback utility for PWA
3 * - iOS 18+: Uses checkbox switch element hack
4 * - Android: Uses Vibration API
5 * - Other: Silently does nothing
6 */
7
8// Platform detection
9const isIOS = /iPhone|iPad/.test(navigator.userAgent);
10const hasVibrate = 'vibrate' in navigator;
11
12// Lazy-initialized hidden elements for iOS
13let checkbox = null;
14let label = null;
15
16function ensureElements() {
17 if (checkbox) return;
18
19 checkbox = document.createElement('input');
20 checkbox.type = 'checkbox';
21 checkbox.setAttribute('switch', '');
22 checkbox.id = 'haptic-trigger';
23 checkbox.style.cssText = 'position:fixed;left:-9999px;opacity:0;pointer-events:none;';
24
25 label = document.createElement('label');
26 label.htmlFor = 'haptic-trigger';
27 label.style.cssText = 'position:fixed;left:-9999px;opacity:0;pointer-events:none;';
28
29 document.body.append(checkbox, label);
30}
31
32/**
33 * Trigger a light haptic tap
34 */
35export function trigger() {
36 if (isIOS) {
37 ensureElements();
38 label.click();
39 } else if (hasVibrate) {
40 navigator.vibrate(10);
41 }
42}
43
44/**
45 * Check if haptics are supported on this device
46 */
47export function isSupported() {
48 return isIOS || hasVibrate;
49}