vp-menu-link.vue 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. <script lang="ts" setup>
  2. import { useRoute } from 'vitepress'
  3. import { useStorage } from '@vueuse/core'
  4. import VPLink from '../common/vp-link.vue'
  5. import { isActiveLink } from '../../utils'
  6. import type { Link } from '../../types'
  7. const USER_VISITED_NEW_RESOURCE_PAGE = 'USER_VISITED_NEW_RESOURCE_PAGE'
  8. defineProps<{
  9. item: Link
  10. }>()
  11. const route = useRoute()
  12. const isVisited = useStorage<boolean | string>(USER_VISITED_NEW_RESOURCE_PAGE, false)
  13. const isNewPage = (item: Link) => item.activeMatch === '/some_fake_path/'
  14. const onNavClick = (item: Link) => {
  15. if (isNewPage(item) && !isVisited.value) {
  16. isVisited.value = Date.now().toString()
  17. }
  18. }
  19. </script>
  20. <template>
  21. <VPLink
  22. :class="{
  23. 'is-menu-link': true,
  24. active: isActiveLink(route, item.activeMatch || item.link, !!item.activeMatch),
  25. }"
  26. :href="item.link"
  27. :no-icon="true"
  28. @click="onNavClick(item)"
  29. >
  30. <el-badge v-if="isNewPage(item) && !isVisited" is-dot class="badge"> {{ item.text }}</el-badge>
  31. <template v-else> {{ item.text }}</template>
  32. </VPLink>
  33. </template>
  34. <style scoped lang="scss">
  35. .is-menu-link {
  36. display: block;
  37. padding: 0 12px;
  38. line-height: calc(var(--nav-height) - 3px);
  39. font-size: 14px;
  40. font-weight: 500;
  41. color: var(--text-color);
  42. transition: color var(--el-transition-duration);
  43. border-bottom: 2px solid transparent;
  44. &.active {
  45. border-bottom-color: var(--brand-color);
  46. }
  47. &:hover {
  48. color: var(--brand-color);
  49. }
  50. .badge {
  51. display: inline;
  52. vertical-align: unset;
  53. }
  54. .badge:deep(.is-dot) {
  55. right: 0;
  56. }
  57. }
  58. </style>