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: 'API Reference', link: '/guide/api' },
{ text: 'Deploying', link: '/guide/deploying' }
]
],
collapsible: true
},
{
text: 'Theme',
@ -77,7 +78,8 @@ function sidebarGuide() {
{ text: 'Homepage', link: '/guide/theme-homepage' },
{ text: 'Footer', link: '/guide/theme-footer' },
{ text: 'Carbon Ads', link: '/guide/theme-carbon-ads' }
]
],
collapsible: true
},
{
text: 'Migrations',
@ -90,7 +92,8 @@ function sidebarGuide() {
text: 'Migration from VitePress 0.x',
link: '/guide/migration-from-vitepress-0'
}
]
],
collapsible: true
}
]
}

@ -34,7 +34,7 @@ watchPostEffect(async () => {
</span>
<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>
</nav>
</aside>

@ -1,31 +1,68 @@
<script lang="ts" setup>
import { useData } from 'vitepress'
import { onMounted, ref } from 'vue'
import { DefaultTheme } from '../config'
import VPSidebarLink from './VPSidebarLink.vue'
const props = defineProps<{
text: string
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>
<template>
<section class="VPSidebarGroup">
<div class="title">
<div class="title" :class="{ collapsible }" @click="toggle">
<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>
<template v-for="item in items" :key="item.link">
<VPSidebarLink :item="item" />
</template>
<div class="items" :class="{ collapsed }" ref="itemsDiv">
<template v-for="item in items" :key="item.link">
<VPSidebarLink :item="item" />
</template>
</div>
</section>
</template>
<style scoped>
.title {
padding: 6px 0;
display: flex;
z-index: 2;
}
.title.collapsible {
cursor: pointer;
}
.title-text {
@ -35,4 +72,31 @@ const { page } = useData()
color: var(--vp-c-text-1);
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>

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

Loading…
Cancel
Save