Radio.vue 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <template>
  2. <div
  3. :class="[
  4. 'ptc-radio',
  5. {
  6. 'ptc-radio--checked': checked,
  7. 'ptc-radio--disabled': !checked && disabled,
  8. },
  9. ]"
  10. @click="onClick"
  11. >
  12. <slot />
  13. </div>
  14. </template>
  15. <script setup lang="ts">
  16. import { inject, computed } from 'vue'
  17. const props = defineProps<{
  18. value: any
  19. modelValue?: any
  20. disabled?: boolean
  21. }>()
  22. const emit = defineEmits<{
  23. (e: 'update:modelValue', value: any): void
  24. (e: 'change', value: any): void
  25. }>()
  26. const parent = inject<any>('RadioGroup')
  27. const checked = computed(
  28. () => props.value === (parent ? parent.modelValue.value : props.modelValue)
  29. )
  30. function onClick() {
  31. if (checked.value) return
  32. const _emit = parent?.emit || emit
  33. _emit('update:modelValue', props.value)
  34. _emit('change', props.value)
  35. }
  36. </script>
  37. <style lang="scss">
  38. .ptc-radio {
  39. position: relative;
  40. border-radius: 8px;
  41. border: 2px solid #d9d9d9;
  42. color: #666;
  43. cursor: pointer;
  44. &--checked {
  45. border-color: $primary-color;
  46. color: $primary-color;
  47. &::after {
  48. content: '';
  49. position: absolute;
  50. right: -1px;
  51. bottom: -1px;
  52. @include icon('@img/check.png', 68px, 72px);
  53. }
  54. }
  55. &--disabled {
  56. color: #999;
  57. background: #ececec;
  58. pointer-events: none;
  59. cursor: not-allowed;
  60. }
  61. &:not(.ptc-radio--checked) [class*='icon-'] {
  62. filter: grayscale(1);
  63. opacity: 0.65;
  64. }
  65. }
  66. </style>