Light on Button (Fluent Like)

by mgoetzke

HTML

<script src="https://unpkg.com/vue"></script>
<div id="app">
  <button id="1" class="lightable">
    Some Button
  </button>
  <button id="dark">
    Dark button
  </button>
  <button id="2" class="lightable">
    Some Other Button
  </button>
  <div ref="light" class="light hidden"></div>
</div>

CSS

button {
  background: lightblue;
  border: 1px solid darkblue;
  padding: 12px;
  position: relative;
}

.light {
  opacity: 0;
  transition: opacity 0.1s;
  pointer-events: none;
  position: fixed;
  width: 80px;
  height: 80px;
  mix-blend-mode: screen;
  background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.3) 20%, rgba(255, 255, 255, 0) 50%);
}

.light-on {
  opacity: 1;
}

JavaScript

new Vue({
  el: '#app',
  mounted() {
    this.isLightOn = false
    this.$el.onmousemove = (e) => this.onmousemove(e)
    this.$el.onmouseleave = (e) => this.lightOff()
  },
  methods: {
   lightOn() {
      if (this.isLightOn)
        return;
      this.$refs.light.classList.add('light-on')
      this.isLightOn = true
    },
    lightOff() {
      if (!this.isLightOn)
        return;
      this.$refs.light.classList.remove('light-on')
      this.isLightOn = false
    },
    onmousemove(e) {
      const el = document.elementFromPoint(e.clientX, e.clientY)

      if (el.classList.contains('lightable')) {
        this.lightOn()
      } else {
        this.lightOff()
      }

      requestAnimationFrame(()=>{      
        const baseOffset = -40;
        this.$refs.light.style.left = `${baseOffset + e.clientX}px`
        this.$refs.light.style.top = `${baseOffset + e.clientY}px`
      })
    },
   
  }
})