Skip to content

Commit 97f9469

Browse files
committed
fix(theme): deep watch sidebar groups and force render on match change
closes #3613
1 parent 387acf7 commit 97f9469

File tree

3 files changed

+77
-22
lines changed

3 files changed

+77
-22
lines changed

Diff for: src/client/theme-default/components/VPSidebar.vue

+18-19
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useScrollLock } from '@vueuse/core'
33
import { inBrowser } from 'vitepress'
44
import { ref, watch } from 'vue'
55
import { useSidebar } from '../composables/sidebar'
6-
import VPSidebarItem from './VPSidebarItem.vue'
6+
import VPSidebarGroup from './VPSidebarGroup.vue'
77
88
const { sidebarGroups, hasSidebar } = useSidebar()
99
@@ -25,6 +25,16 @@ watch(
2525
},
2626
{ immediate: true, flush: 'post' }
2727
)
28+
29+
const key = ref(0)
30+
31+
watch(
32+
sidebarGroups,
33+
() => {
34+
key.value += 1
35+
},
36+
{ deep: true }
37+
)
2838
</script>
2939

3040
<template>
@@ -37,17 +47,18 @@ watch(
3747
>
3848
<div class="curtain" />
3949

40-
<nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1">
50+
<nav
51+
class="nav"
52+
id="VPSidebarNav"
53+
aria-labelledby="sidebar-aria-label"
54+
tabindex="-1"
55+
>
4156
<span class="visually-hidden" id="sidebar-aria-label">
4257
Sidebar Navigation
4358
</span>
4459

4560
<slot name="sidebar-nav-before" />
46-
47-
<div v-for="item in sidebarGroups" :key="item.text" class="group">
48-
<VPSidebarItem :item="item" :depth="0" />
49-
</div>
50-
61+
<VPSidebarGroup :items="sidebarGroups" :key="key" />
5162
<slot name="sidebar-nav-after" />
5263
</nav>
5364
</aside>
@@ -122,16 +133,4 @@ watch(
122133
.nav {
123134
outline: 0;
124135
}
125-
126-
.group + .group {
127-
border-top: 1px solid var(--vp-c-divider);
128-
padding-top: 10px;
129-
}
130-
131-
@media (min-width: 960px) {
132-
.group {
133-
padding-top: 10px;
134-
width: calc(var(--vp-sidebar-width) - 64px);
135-
}
136-
}
137136
</style>
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<script setup lang="ts">
2+
import type { DefaultTheme } from 'vitepress/theme'
3+
import { onBeforeUnmount, onMounted, ref } from 'vue'
4+
import VPSidebarItem from './VPSidebarItem.vue'
5+
6+
defineProps<{
7+
items: DefaultTheme.SidebarItem[]
8+
}>()
9+
10+
const disableTransition = ref(true)
11+
12+
let timer: ReturnType<typeof setTimeout> | null = null
13+
14+
onMounted(() => {
15+
timer = setTimeout(() => {
16+
timer = null
17+
disableTransition.value = false
18+
}, 300)
19+
})
20+
21+
onBeforeUnmount(() => {
22+
if (timer != null) {
23+
clearTimeout(timer)
24+
timer = null
25+
}
26+
})
27+
</script>
28+
29+
<template>
30+
<div
31+
v-for="item in items"
32+
:key="item.text"
33+
class="group"
34+
:class="{ 'no-transition': disableTransition }"
35+
>
36+
<VPSidebarItem :item="item" :depth="0" />
37+
</div>
38+
</template>
39+
40+
<style scoped>
41+
.no-transition :deep(.caret-icon) {
42+
transition: none;
43+
}
44+
45+
.group + .group {
46+
border-top: 1px solid var(--vp-c-divider);
47+
padding-top: 10px;
48+
}
49+
50+
@media (min-width: 960px) {
51+
.group {
52+
padding-top: 10px;
53+
width: calc(var(--vp-sidebar-width) - 64px);
54+
}
55+
}
56+
</style>

Diff for: src/client/theme-default/components/VPSidebarItem.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
2-
import { computed } from 'vue'
32
import type { DefaultTheme } from 'vitepress/theme'
3+
import { computed } from 'vue'
44
import { useSidebarControl } from '../composables/sidebar'
55
import VPLink from './VPLink.vue'
66
@@ -27,8 +27,8 @@ const textTag = computed(() => {
2727
return !hasChildren.value
2828
? 'p'
2929
: props.depth + 2 === 7
30-
? 'p'
31-
: `h${props.depth + 2}`
30+
? 'p'
31+
: `h${props.depth + 2}`
3232
})
3333
3434
const itemRole = computed(() => (isLink.value ? undefined : 'button'))

0 commit comments

Comments
 (0)