feat: allow collapsible sidebar items

pull/663/head
Divyansh Singh 3 years ago
parent 607c3d33f3
commit 1a18ca8dcb

@ -67,7 +67,8 @@ function sidebarGuide() {
{ text: 'Using Vue in Markdown', link: '/guide/using-vue' }, { text: 'Using Vue in Markdown', link: '/guide/using-vue' },
{ text: 'API Reference', link: '/guide/api' }, { text: 'API Reference', link: '/guide/api' },
{ text: 'Deploying', link: '/guide/deploying' } { text: 'Deploying', link: '/guide/deploying' }
] ],
collapsible: true
}, },
{ {
text: 'Theme', text: 'Theme',
@ -77,7 +78,8 @@ function sidebarGuide() {
{ text: 'Homepage', link: '/guide/theme-homepage' }, { text: 'Homepage', link: '/guide/theme-homepage' },
{ text: 'Footer', link: '/guide/theme-footer' }, { text: 'Footer', link: '/guide/theme-footer' },
{ text: 'Carbon Ads', link: '/guide/theme-carbon-ads' } { text: 'Carbon Ads', link: '/guide/theme-carbon-ads' }
] ],
collapsible: true
}, },
{ {
text: 'Migrations', text: 'Migrations',
@ -90,7 +92,8 @@ function sidebarGuide() {
text: 'Migration from VitePress 0.x', text: 'Migration from VitePress 0.x',
link: '/guide/migration-from-vitepress-0' link: '/guide/migration-from-vitepress-0'
} }
] ],
collapsible: true
} }
] ]
} }

@ -34,7 +34,7 @@ watchPostEffect(async () => {
</span> </span>
<div v-for="group in sidebar" :key="group.text" class="group"> <div v-for="group in sidebar" :key="group.text" class="group">
<VPSidebarGroup :text="group.text" :items="group.items" /> <VPSidebarGroup :text="group.text" :items="group.items" :collapsible="group.collapsible" />
</div> </div>
</nav> </nav>
</aside> </aside>

@ -1,31 +1,68 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useData } from 'vitepress' import { onMounted, ref } from 'vue'
import { DefaultTheme } from '../config' import { DefaultTheme } from '../config'
import VPSidebarLink from './VPSidebarLink.vue' import VPSidebarLink from './VPSidebarLink.vue'
const props = defineProps<{ const props = defineProps<{
text: string text: string
items: DefaultTheme.SidebarItem[] items: DefaultTheme.SidebarItem[]
collapsible?: boolean
}>() }>()
const { page } = useData() const collapsed = ref(false)
const itemsDiv = ref<HTMLDivElement | null>(null)
const height = ref('')
const storeHeight = () => {
height.value = itemsDiv.value?.clientHeight + 'px'
}
const toggle = () => {
if (!props.collapsible) return
if (!collapsed.value) storeHeight()
collapsed.value = !collapsed.value
}
onMounted(storeHeight)
</script> </script>
<template> <template>
<section class="VPSidebarGroup"> <section class="VPSidebarGroup">
<div class="title"> <div class="title" :class="{ collapsible }" @click="toggle">
<h2 class="title-text">{{ text }}</h2> <h2 class="title-text">{{ text }}</h2>
<svg
v-if="collapsible"
xmlns="http://www.w3.org/2000/svg"
class="chevron"
:class="{ collapsed }"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
/>
</svg>
</div> </div>
<template v-for="item in items" :key="item.link"> <div class="items" :class="{ collapsed }" ref="itemsDiv">
<VPSidebarLink :item="item" /> <template v-for="item in items" :key="item.link">
</template> <VPSidebarLink :item="item" />
</template>
</div>
</section> </section>
</template> </template>
<style scoped> <style scoped>
.title { .title {
padding: 6px 0; padding: 6px 0;
display: flex;
z-index: 2;
}
.title.collapsible {
cursor: pointer;
} }
.title-text { .title-text {
@ -35,4 +72,31 @@ const { page } = useData()
color: var(--vp-c-text-1); color: var(--vp-c-text-1);
transition: color 0.5s; transition: color 0.5s;
} }
.chevron {
height: 20px;
margin-left: 5px;
transition: transform 0.5s;
}
.chevron.collapsed {
transform: rotate(-90deg);
}
.items {
height: v-bind('height');
transition: height 0.5s;
overflow: hidden;
}
.items.collapsed {
height: 0;
margin-bottom: -22px;
}
@media (min-width: 960px) {
.items.collapsed {
margin-bottom: -14px;
}
}
</style> </style>

@ -82,6 +82,7 @@ export namespace DefaultTheme {
export interface SidebarGroup { export interface SidebarGroup {
text: string text: string
items: SidebarItem[] items: SidebarItem[]
collapsible?: boolean
} }
export interface SidebarItem { export interface SidebarItem {

Loading…
Cancel
Save