IndicatorLight.vue 1.66 KB
<script lang="ts" setup>
const props = defineProps<{
  value?: boolean
}>()

const emit = defineEmits(['update:value', 'change'])

const handleChange = (event: Event) => {
  const _value = (event.target as HTMLInputElement).checked
  emit('update:value', _value)
  emit('change', _value)
}
</script>

<template>
  <label class="indicator-light-switch">
    <input :value="props.value" :checked="props.value" type="checkbox" @change="handleChange">
    <div class="panel" />
  </label>
</template>

<style scoped lang="less">
.indicator-light-switch {
  input[type='checkbox'] {
    display: none;
  }
  .panel {
    position: relative;
    width: 60px;
    height: 60px;
    cursor: pointer;
    border-radius: 50%;
    background: linear-gradient(#dedede, #fdfdfd);
    box-shadow: 0 3px 5px rgb(0 0 0 / 25%), inset 0 1px 0 hsl(0deg 0% 100% / 30%), inset 0 -5px 5px hsl(0deg 0% 39% / 10%), inset 0 5px 5px hsl(0deg 0% 100% / 30%);
  }

  .panel::after,
  .panel::before {
    content: '';
    position: absolute;
    width: 20%;
    height: 20%;
    border-radius: 50%;
    left: 40%;
    top: 40%;
  }

  input:checked ~ .panel::after {
    display: none;
  }

  input:not(:checked) ~ .panel::before {
    display: none;
  }

  input:not(:checked) ~ .panel {
    background: linear-gradient(#EAEAEA, #eaeaea);
  }

  .panel::after {
    background-color: #ddd;
    background: radial-gradient(40% 35%, #ccc, #969696 60%);
    box-shadow: inset 0 2px 1px rgb(0 0 0 / 15%), 0 2px 5px hsl(0deg 0% 78% / 10%);
  }

  .panel::before {
    background-color: #25d025;
    box-shadow: inset 0 3px 5px 1px rgb(0 0 0 / 10%), 0 1px 0 hsl(0deg 0% 100% / 40%), 0 0 10px 2px rgb(0 210 0 / 50%);
  }
}
</style>