A bit of feedback…

A small bit of feedback… that’s often what a mobile user is looking for. Haptic feedback – a quick device vibration – is great. It’s subtle, quick, doesn’t interrupt, but gives an actual *feeling* that something happened. And… on iOS, it’s harder to do without building a full ‘native mobile app’. iOS Safari doesn’t support the ‘vibrate’ method. Apple does do some things quite well, but holding off on browser support for this has just been… annoying.

Some time ago Apple introduced a ‘toggle switch’ attribute on the ‘checkbox’ input type. And clicking it… provides small haptic feedback. And this morning I found a small React hook that will trigger this for you.

I created a similar version for Vue 3

import { ref, computed, onMounted, onUnmounted } from 'vue'

const HAPTIC_DURATION = 10

function detectIOS(): boolean {
  return /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream
}

export function useHaptic(duration = HAPTIC_DURATION) {
  const inputRef = ref<HTMLInputElement | null>(null)
  const labelRef = ref<HTMLLabelElement | null>(null)
  const isIOS = computed(() => detectIOS())

  onMounted(() => {
    const input = document.createElement('input')
    input.type = 'checkbox'
    input.id = 'haptic-switch'
    input.setAttribute('switch', '')
    input.style.display = 'none'
    document.body.appendChild(input)
    inputRef.value = input

    const label = document.createElement('label')
    label.htmlFor = 'haptic-switch'
    label.style.display = 'none'
    document.body.appendChild(label)
    labelRef.value = label
  })

  onUnmounted(() => {
    if (inputRef.value) document.body.removeChild(inputRef.value)
    if (labelRef.value) document.body.removeChild(labelRef.value)
  })

  function triggerHaptic() {
    if (!isIOS.value && navigator?.vibrate) {
      navigator.vibrate(duration)
    } else {
      labelRef.value?.click()
    }
  }

  return { triggerHaptic }
}

Which can then be used as so…

<script setup lang="ts">
import { useHaptic } from '@/composables/useHaptic';

const { triggerHaptic } = useHaptic();
....

function handleClick(type: string) {
    triggerHaptic();
// other code here
}
...

Simple, and it works just fine.

Maybe in 2027 we’ll get the ability to provide haptic feedback in regular web apps natively without hacks?

Similar Posts

  • Bad I9 PDF form

    Have been needing to programmatically fill out an I9 PDF, retrieved from gov site. Should be fairly straightforward, right? Well… the field names are… a mess. Field names like topmostSubform[0].Page1[0].U\.S\._Social_Security_Number__Last_4_numbers_[0]topmostSubform[0].Page1[0].expiration_date__if_applicable__mm_dd_yyyy[0] topmostSubform[0].Page2[0].Employers_Business_or_Organization_Address_Street_Number_and_Name[0] and so on make it pretty… not straightforward to create a usable key/value combination to search and replace. But… today, I noticed it got…

  • k as in knife

    Many moons ago my earlier version of my blog had this list I use when spelling things for people over the phone. I managed to find it at archive.org and thought I’d repost… a as in aisle (or aye) b as in bdellium  c as in czar d as in djibouti e as in eight…

  • chunked file uploads with plupload

    Holy tamole… Have been wrestling with a client project using ‘plupload’ with a user base consistently uploading files from 150-500meg on a daily basis. They’d been uploading to youtube/vimeo mostly, because the experience with the older uploader (still plupload earlier version) was bad – slow, mostly, but some issues about determining whether items were uploaded/processed…

Leave a Reply

Your email address will not be published. Required fields are marked *