HBadge.vue 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. <script setup lang="ts">
  2. const props = defineProps<{
  3. value: string | number | boolean
  4. }>()
  5. const show = computed(() => {
  6. switch (typeof props.value) {
  7. case 'string':
  8. return props.value.length > 0
  9. case 'number':
  10. return props.value > 0
  11. case 'boolean':
  12. return props.value
  13. default:
  14. return props.value !== undefined && props.value !== null
  15. }
  16. })
  17. const transitionClass = ref({
  18. enterActiveClass: 'ease-in-out duration-500',
  19. enterFromClass: 'opacity-0',
  20. enterToClass: 'opacity-100',
  21. leaveActiveClass: 'ease-in-out duration-500',
  22. leaveFromClass: 'opacity-100',
  23. leaveToClass: 'opacity-0',
  24. })
  25. </script>
  26. <template>
  27. <div class="relative inline-flex">
  28. <slot />
  29. <Transition v-bind="transitionClass">
  30. <span
  31. v-if="show"
  32. class="absolute start-[50%] top-0 z-20 whitespace-nowrap rounded-full bg-ui-primary px-1.5 text-xs text-ui-text ring-1 ring-light -translate-y-[50%] dark-ring-dark"
  33. :class="{ '-indent-9999 w-1.5 h-1.5 px-0! start-[100%]! -translate-x-[50%] rtl:(translate-x-[50%]) before:(content-empty block bg-ui-primary w-full h-full rounded-full absolute start-0 top-0 animate-ping)': value === true }"
  34. >
  35. {{ value }}
  36. </span>
  37. </Transition>
  38. </div>
  39. </template>