fix(theme): deep watch sidebar groups and force render on match change

closes #3613
pull/4014/head
Divyansh Singh 1 year ago
parent 387acf71aa
commit 97f9469b6d

@ -3,7 +3,7 @@ import { useScrollLock } from '@vueuse/core'
import { inBrowser } from 'vitepress'
import { ref, watch } from 'vue'
import { useSidebar } from '../composables/sidebar'
import VPSidebarItem from './VPSidebarItem.vue'
import VPSidebarGroup from './VPSidebarGroup.vue'
const { sidebarGroups, hasSidebar } = useSidebar()
@ -25,6 +25,16 @@ watch(
},
{ immediate: true, flush: 'post' }
)
const key = ref(0)
watch(
sidebarGroups,
() => {
key.value += 1
},
{ deep: true }
)
</script>
<template>
@ -37,17 +47,18 @@ watch(
>
<div class="curtain" />
<nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1">
<nav
class="nav"
id="VPSidebarNav"
aria-labelledby="sidebar-aria-label"
tabindex="-1"
>
<span class="visually-hidden" id="sidebar-aria-label">
Sidebar Navigation
</span>
<slot name="sidebar-nav-before" />
<div v-for="item in sidebarGroups" :key="item.text" class="group">
<VPSidebarItem :item="item" :depth="0" />
</div>
<VPSidebarGroup :items="sidebarGroups" :key="key" />
<slot name="sidebar-nav-after" />
</nav>
</aside>
@ -122,16 +133,4 @@ watch(
.nav {
outline: 0;
}
.group + .group {
border-top: 1px solid var(--vp-c-divider);
padding-top: 10px;
}
@media (min-width: 960px) {
.group {
padding-top: 10px;
width: calc(var(--vp-sidebar-width) - 64px);
}
}
</style>

@ -0,0 +1,56 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import { onBeforeUnmount, onMounted, ref } from 'vue'
import VPSidebarItem from './VPSidebarItem.vue'
defineProps<{
items: DefaultTheme.SidebarItem[]
}>()
const disableTransition = ref(true)
let timer: ReturnType<typeof setTimeout> | null = null
onMounted(() => {
timer = setTimeout(() => {
timer = null
disableTransition.value = false
}, 300)
})
onBeforeUnmount(() => {
if (timer != null) {
clearTimeout(timer)
timer = null
}
})
</script>
<template>
<div
v-for="item in items"
:key="item.text"
class="group"
:class="{ 'no-transition': disableTransition }"
>
<VPSidebarItem :item="item" :depth="0" />
</div>
</template>
<style scoped>
.no-transition :deep(.caret-icon) {
transition: none;
}
.group + .group {
border-top: 1px solid var(--vp-c-divider);
padding-top: 10px;
}
@media (min-width: 960px) {
.group {
padding-top: 10px;
width: calc(var(--vp-sidebar-width) - 64px);
}
}
</style>

@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { DefaultTheme } from 'vitepress/theme'
import { computed } from 'vue'
import { useSidebarControl } from '../composables/sidebar'
import VPLink from './VPLink.vue'

Loading…
Cancel
Save