profectus-docs/docs/.vitepress/theme/home/NavLink.vue

98 lines
No EOL
1.9 KiB
Vue

<script setup lang="ts">
import { computed, toRefs } from 'vue'
import { useRoute, withBase } from 'vitepress'
const props = defineProps<{
item: {
text: string
target?: string
rel?: string
ariaLabel?: string
activeMatch?: string
link: string
}
}>()
const propsRefs = toRefs(props)
const route = useRoute()
const linkProps = computed(() => {
const routePath = normalizePath(`/${route.data.relativePath}`)
let active = false
if (propsRefs.item.value.activeMatch) {
active = new RegExp(propsRefs.item.value.activeMatch).test(routePath)
} else {
const itemPath = normalizePath(propsRefs.item.value.link)
active =
itemPath === '/'
? itemPath === routePath
: routePath.startsWith(itemPath)
}
return {
class: {
active
},
href: withBase(propsRefs.item.value.link),
target: propsRefs.item.value.target || null,
rel: propsRefs.item.value.rel || null,
'aria-label': propsRefs.item.value.ariaLabel
}
})
function normalizePath(path: string): string {
return path
.replace(/#.*$/, '')
.replace(/\?.*$/, '')
.replace(/\.(html|md)$/, '')
.replace(/\/index$/, '/')
}
</script>
<template>
<div class="nav-link">
<a class="item" v-bind="linkProps">
{{ item.text }}
</a>
</div>
</template>
<style scoped>
.item {
display: block;
padding: 0 1.5rem;
line-height: 36px;
font-size: 1rem;
font-weight: 600;
color: var(--c-text);
white-space: nowrap;
}
.item:hover,
.item.active {
text-decoration: none;
color: var(--c-brand);
}
.item.external:hover {
border-bottom-color: transparent;
color: var(--c-text);
}
@media (min-width: 720px) {
.item {
border-bottom: 2px solid transparent;
padding: 0;
line-height: 24px;
font-size: 0.9rem;
font-weight: 500;
}
.item:hover,
.item.active {
border-bottom-color: var(--c-brand);
color: var(--c-text);
}
}
</style>