Home > Software engineering >  How to detect hover state on touchscreen device - Vue 3
How to detect hover state on touchscreen device - Vue 3

Time:04-15

In my case in desktop mode user can hover over the element to reveal the menu. User can also click the element that makes a request to the server.

In touchscreen mode, I would like the click to be revealing the menu instead of making a request.

It seems like impossible task to achieve unless I start going outside of vue and changing css directly from DOM level.

<script setup>
import { ref } from "vue";

const text = ref("whatever");
const isEditing = ref(false);
function sendToServer() {
  console.log("Sending request of ", text.value, " to server.")
  isEditing.value = false;
}
</script>

<template>
  <div >
    <span v-show="!isEditing" @click="sendToServer" @touchstart.prevent> {{ text }}</span>
    <input v-show="isEditing" v-model="text">
    <span @click="sendToServer" >➡️</span>
    <span @click="isEditing = !isEditing" >✏️</span>
  </div>
</template>

<style>
  .icon {
    opacity: 0;
  }
  
  .wrapper:hover .icon {
    opacity: 1;
  }
  
  .wrapper > span {
    cursor: pointer;
  }
</style>

Vue SFC playground link

CodePudding user response:

"It seems like impossible task to achieve unless I start going outside of vue and changing css directly from DOM level."

I would say it is impossible to achieve with CSS-only, but Vue (IMHO) seems cable and well suited to handle that.

Instead of using css :hover you will need to manage the visibility using state (isSelected in example)

then use @touchstart to toggle visibility - this will only be available to touch devices and mouse events @mouseover to show and @mouseout to hide.

there may be some more finessing to handle some edge cases, but this is how I'd implement it. For example, you may need a global touch event listener to hide when user clicks outside of the text.

<script setup>
  import { ref } from "vue";

  const text = ref("whatever");
  const isEditing = ref(false);
  const isSelected = ref(false);
  function toggleIsSelected(){
        isSelected.value = !isSelected.value
  }
  function unselect(){
    isSelected.value = false;
  }
  function sendToServer() {
    console.log("Sending request of ", text.value, " to server.")
    isEditing.value = false;
  }
</script>

<template>
  <div >
    <span v-show="!isEditing"
          @click="sendToServer"
          @touchstart=toggleIsSelected
          @mouseover=toggleIsSelected
          @mouseout=unselect
    > {{ text }}</span>
    <input v-show="isEditing" v-model="text">
    <span v-show=isSelected @click="sendToServer" >➡️</span>
    <span v-show=isSelected @click="isEditing = !isEditing" >✏️</span>
  </div>
</template>

<style>
  .wrapper > span {
    cursor: pointer;
  }
</style>
  • Related