Skip to content

Commit 9547863

Browse files
docs: highlight toc based on active headers
1 parent 33feacf commit 9547863

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

packages/docs/src/components/app/Heading.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<component
33
:is="component"
4+
v-intersect="href ? onIntersect : undefined"
45
:class="classes"
56
>
67
<router-link
@@ -22,6 +23,10 @@
2223
<script setup>
2324
// Utilities
2425
import { computed } from 'vue'
26+
import { storeToRefs } from 'pinia'
27+
28+
// Composables
29+
import { useAppStore } from '@/store/app'
2530
2631
const HEADING_CLASSES = {
2732
1: 'text-h3 text-sm-h3',
@@ -31,6 +36,8 @@
3136
5: 'text-subtitle-1 font-weight-medium',
3237
}
3338
39+
const { activeHeaders } = storeToRefs(useAppStore())
40+
3441
const props = defineProps({
3542
content: String,
3643
href: String,
@@ -39,6 +46,17 @@
3946
4047
const component = computed(() => `h${props.level}`)
4148
const classes = computed(() => ['v-heading', 'mb-2', HEADING_CLASSES[props.level]])
49+
50+
function onIntersect (isIntersecting) {
51+
if (isIntersecting) {
52+
if (!activeHeaders.value.hrefs.includes(props.href)) {
53+
activeHeaders.value.hrefs.push(props.href)
54+
}
55+
} else if (!isIntersecting && activeHeaders.value.hrefs.includes(props.href)) {
56+
activeHeaders.value.hrefs.splice(activeHeaders.value.hrefs.indexOf(props.href), 1)
57+
}
58+
activeHeaders.value.temp = !isIntersecting && !activeHeaders.value.hrefs.length ? props.href : ''
59+
}
4260
</script>
4361

4462
<style lang="sass">

packages/docs/src/components/app/Toc.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<v-navigation-drawer
33
v-if="!route.meta.fluid"
44
id="app-toc"
5-
v-model="app.toc"
5+
v-model="tocDrawer"
66
color="background"
77
floating
88
location="right"
@@ -29,10 +29,9 @@
2929
>
3030
<li
3131
:class="[
32-
'ps-3 text-body-2 py-1 font-weight-regular',
32+
'ps-3 text-medium-emphasis text-body-2 py-1 font-weight-regular',
3333
{
34-
'text-primary router-link-active': route.hash === to,
35-
'text-medium-emphasis': route.hash !== to,
34+
'text-primary router-link-active': activeHeaders.temp == to || activeHeaders.hrefs.includes(to),
3635
'ps-6': level === 3,
3736
'ps-9': level === 4,
3837
'ps-12': level === 5,
@@ -126,6 +125,7 @@
126125
127126
// Composables
128127
import { RouteLocation, Router, useRoute, useRouter } from 'vue-router'
128+
import { storeToRefs } from 'pinia'
129129
import { useAppStore } from '@/store/app'
130130
// import { useGtag } from 'vue-gtag-next'
131131
import { useSponsorsStore } from '@/store/sponsors'
@@ -141,7 +141,7 @@
141141
level: number;
142142
}
143143
144-
const app = useAppStore()
144+
const { toc: tocDrawer, activeHeaders } = storeToRefs(useAppStore())
145145
146146
function useUpdateHashOnScroll (route: RouteLocation, router: Router) {
147147
const scrolling = ref(false)

packages/docs/src/store/app.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export type Category = {
1212

1313
export type RootState = {
1414
apiSearch: string
15+
activeHeaders: {
16+
hrefs: string[]
17+
temp: string
18+
}
1519
drawer: boolean | null
1620
toc: boolean | null
1721
items: NavItem[]
@@ -33,6 +37,10 @@ export const useAppStore = defineStore({
3337
id: 'app',
3438
state: () => ({
3539
apiSearch: '',
40+
activeHeaders: {
41+
hrefs: [],
42+
temp: '',
43+
},
3644
drawer: null,
3745
toc: null,
3846
items: Array.from(data),

0 commit comments

Comments
 (0)