Switch.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. <template>
  2. <span
  3. class="switch"
  4. :class="{
  5. 'active': value,
  6. 'disabled': disabled,
  7. }"
  8. @click="handleChange()"
  9. >
  10. <span class="switch-core"></span>
  11. </span>
  12. </template>
  13. <script lang="ts" setup>
  14. const props = withDefaults(defineProps<{
  15. value: boolean
  16. disabled?: boolean
  17. }>(), {
  18. disabled: false,
  19. })
  20. const emit = defineEmits<{
  21. (event: 'update:value', payload: boolean): void
  22. }>()
  23. const handleChange = () => {
  24. if (props.disabled) return
  25. emit('update:value', !props.value)
  26. }
  27. </script>
  28. <style lang="scss" scoped>
  29. .switch {
  30. // height: 20px;
  31. // display: inline-block;
  32. display: flex;
  33. align-items: center;
  34. cursor: pointer;
  35. &:not(.disabled).active {
  36. .switch-core {
  37. border-color: #f6c82b;
  38. background-color: #f6c82b;
  39. &::after {
  40. left: 100%;
  41. margin-left: -17px;
  42. }
  43. }
  44. }
  45. &.disabled {
  46. cursor: default;
  47. .switch-core::after {
  48. background-color: #f5f5f5;
  49. }
  50. }
  51. }
  52. .switch-core {
  53. margin: 0;
  54. display: inline-block;
  55. position: relative;
  56. width: 40px;
  57. height: 20px;
  58. border: 1px solid #d9d9d9;
  59. outline: none;
  60. border-radius: 10px;
  61. box-sizing: border-box;
  62. background: #d9d9d9;
  63. transition: border-color .3s, background-color .3s;
  64. vertical-align: middle;
  65. &::after {
  66. content: '';
  67. position: absolute;
  68. top: 1px;
  69. left: 1px;
  70. border-radius: 100%;
  71. transition: all .3s;
  72. width: 16px;
  73. height: 16px;
  74. background-color: #fff;
  75. }
  76. }
  77. </style>