vp-sidebar-link.vue 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <script lang="ts" setup>
  2. import { computed, ref, watch } from 'vue'
  3. import { useRoute } from 'vitepress'
  4. import { isActive } from '../../utils'
  5. import type { Link } from '../../types'
  6. const props = defineProps<{
  7. item: Link
  8. }>()
  9. defineEmits(['close'])
  10. const sidebarItem = ref<HTMLElement>()
  11. const route = useRoute()
  12. const activeLink = computed<boolean>(() => isActive(route, props.item.link))
  13. watch([activeLink, sidebarItem], ([active, el]) => {
  14. if (active && el) {
  15. el.scrollIntoView?.({ block: 'nearest' })
  16. }
  17. })
  18. </script>
  19. <template>
  20. <a
  21. ref="sidebarItem"
  22. :class="{
  23. link: true,
  24. active: activeLink,
  25. 'flex items-center': item.promotion,
  26. }"
  27. :href="item.link"
  28. @click="$emit('close')"
  29. >
  30. <p class="link-text">{{ item.text }}</p>
  31. <VersionTag v-if="item.promotion" class="ml-2" :version="item.promotion" />
  32. </a>
  33. </template>
  34. <style scoped lang="scss">
  35. .link:not(.flex) {
  36. display: block;
  37. }
  38. .link {
  39. padding: 10px 16px;
  40. line-height: 1.5;
  41. font-size: 0.9rem;
  42. border-radius: 8px;
  43. .link-text {
  44. margin: 0;
  45. }
  46. }
  47. .link:hover .link-text {
  48. color: var(--brand-color);
  49. transition: color 0.25s;
  50. }
  51. .link.active {
  52. background-color: var(--link-active-bg-color);
  53. .link-text {
  54. font-weight: 600;
  55. color: var(--brand-color);
  56. transition: color 0.25s;
  57. }
  58. }
  59. .link-text {
  60. line-height: 20px;
  61. font-size: 13px;
  62. font-weight: 500;
  63. color: var(--text-color-light);
  64. transition: color 0.5s;
  65. }
  66. </style>