useIsMouseInactive (SolidJS)

Get a signal that lets you know when the mouse has stopped moving for some time.

typescriptjavascript
import {
  Accessor,
  createEffect,
  createMemo,
  createSignal,
  onCleanup,
  onMount,
} from 'solid-js'
 
interface UseIsMouseInactiveOptions {
  timeout?: number
  root: Element | Window | null
}
 
export const useIsMouseInactive = (props: UseIsMouseInactiveOptions) => {
  const [inactive, setInactive] = createSignal(false)
  let timer: ReturnType<typeof setTimeout>
 
  const onMouseMove = () => {
    setInactive(false)
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      setInactive(true)
    }, props.timeout ?? 5000)
  }
 
  createEffect(() => {
    const el = props.root
    if (!el) return
 
    onMount(() => {
      el.addEventListener('mousemove', onMouseMove)
      onMouseMove()
    })
 
    onCleanup(() => {
      el.removeEventListener('mousemove', onMouseMove)
    })
  })
 
  return inactive
}
import { createEffect, createSignal, onCleanup, onMount } from 'solid-js'
 
export const useIsMouseInactive = props => {
  const [inactive, setInactive] = createSignal(false)
  let timer
 
  const onMouseMove = () => {
    setInactive(false)
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      setInactive(true)
    }, props.timeout ?? 5000)
  }
 
  createEffect(() => {
    const el = props.root
    if (!el) return
 
    onMount(() => {
      el.addEventListener('mousemove', onMouseMove)
      onMouseMove()
    })
 
    onCleanup(() => {
      el.removeEventListener('mousemove', onMouseMove)
    })
  })
 
  return inactive
}

Usage

typescriptjavascript
import type { VoidComponent } from 'solid-js'
 
export const Example: VoidComponent = () => {
  const [element, setElement] = createSignal<HTMLElement>()
 
  const isInactive = useIsMouseInactive({
    get root() {
      return element()
    },
  })
 
  return (
    <div class="grid h-96 place-items-center">
      <div
        ref={setElement}
        class="h-64 w-64 bg-red-500"
        classList={{
          // Hide cursor when mouse hasn't moved for a while
          'cursor-none touch-none': isInactive(),
        }}
      />
    </div>
  )
}
export const Example = () => {
  const [element, setElement] = createSignal()
 
  const isInactive = useIsMouseInactive({
    get root() {
      return element()
    },
  })
 
  return (
    <div class="grid h-96 place-items-center">
      <div
        ref={setElement}
        class="h-64 w-64 bg-red-500"
        classList={{
          // Hide cursor when mouse hasn't moved for a while
          'cursor-none touch-none': isInactive(),
        }}
      />
    </div>
  )
}

Demo

Created 27/08/22Updated 07/08/23
Found a mistake, or want to suggest an improvement? Source on GitHub here
and see edit history here