u
This commit is contained in:
1 parent
e99a9fb274
commit
0be0b0767a
788 files changed
+112023
-14941
No files matched your search
@@ -0,0 +1,134 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 侧边栏条目 —— DOM 与类名照抄 Docus / @nuxt/ui 的 ContentNavigation。
|
||||
*
|
||||
* 结构对照(取自 docus.dev 实测 DOM):
|
||||
* 有子项: li.itemWithChildren > button.link.trigger + div.content > ul.listWithChildren
|
||||
* 无子项: li.item > a.link
|
||||
*
|
||||
* 实测样式(docus.dev,1440px,light):
|
||||
* ul.list margin: -6px -10px 0 (-mt-1.5 -mx-2.5)
|
||||
* li.itemWithChildren display:flex; flex-direction:column
|
||||
* button/a.link padding:6px 10px; gap:6px; font-size:14px; border-radius:0
|
||||
* 高度 32px(py-1.5*2 + 行高 20)
|
||||
* 圆角 6px 在 ::before 上(before:rounded-md)
|
||||
* 分组标题(trigger) font-weight:600; color: text-highlighted
|
||||
* 普通项 font-weight:400; color: text-muted
|
||||
* 激活项 font-weight:500; color: text-primary;无背景
|
||||
* ::after 竖线 w=1px h=28px left=-6px top/bottom=2px bg=primary
|
||||
* 图标 width/height:16px(size-4);margin-inline:2px(mx-0.5)
|
||||
* ul.listWithChildren margin-inline-start:20px; border-inline-start:1px;
|
||||
* padding-inline-start:0
|
||||
*/
|
||||
import { computed, ref } from 'vue'
|
||||
import { useData } from 'vitepress'
|
||||
import { isActive } from 'vitepress/dist/client/shared.js'
|
||||
import { sidebarIcons } from './sidebarIcons'
|
||||
|
||||
interface G3SidebarItem {
|
||||
text?: string
|
||||
link?: string
|
||||
/** 图标名(对应 sidebarIcons 的键) */
|
||||
icon?: string
|
||||
rel?: string
|
||||
target?: string
|
||||
collapsed?: boolean
|
||||
items?: G3SidebarItem[]
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
item: G3SidebarItem
|
||||
level: number
|
||||
}>()
|
||||
|
||||
const { page } = useData()
|
||||
|
||||
/** 该条目自身是否就是当前页 */
|
||||
const isActiveLink = computed(() =>
|
||||
props.item.link ? isActive(page.value.relativePath, props.item.link) : false,
|
||||
)
|
||||
|
||||
function treeHasActive(item: G3SidebarItem): boolean {
|
||||
if (item.link && isActive(page.value.relativePath, item.link)) return true
|
||||
return (item.items ?? []).some(treeHasActive)
|
||||
}
|
||||
|
||||
const hasActiveLink = computed(() => treeHasActive(props.item))
|
||||
const hasChildren = computed(() => !!(props.item.items && props.item.items.length))
|
||||
|
||||
/** 折叠状态:local 覆盖 + 子项含当前页时强制展开 */
|
||||
const overridden = ref<boolean | null>(null)
|
||||
const collapsed = computed(() => {
|
||||
if (overridden.value !== null) return overridden.value
|
||||
if (hasActiveLink.value) return false
|
||||
return !!props.item.collapsed
|
||||
})
|
||||
|
||||
function toggle() {
|
||||
overridden.value = !collapsed.value
|
||||
}
|
||||
|
||||
const iconComponent = computed(() =>
|
||||
props.item.icon ? sidebarIcons[props.item.icon] ?? null : null,
|
||||
)
|
||||
|
||||
const linkClass = computed(() => [
|
||||
'g3-nav-link',
|
||||
// trigger(分组标题):font-semibold
|
||||
hasChildren.value ? 'g3-nav-trigger' : '',
|
||||
isActiveLink.value ? 'is-active' : '',
|
||||
{ 'g3-nav-disabled': false },
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 有子项:li.itemWithChildren > button.link + div.content > ul.listWithChildren -->
|
||||
<li v-if="hasChildren" class="g3-item-with-children">
|
||||
<button
|
||||
type="button"
|
||||
:class="linkClass"
|
||||
:aria-expanded="!collapsed"
|
||||
@click="toggle"
|
||||
>
|
||||
<component
|
||||
:is="iconComponent"
|
||||
v-if="iconComponent"
|
||||
class="g3-nav-icon"
|
||||
:size="16"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span class="g3-nav-title">{{ item.text }}</span>
|
||||
</button>
|
||||
|
||||
<div v-show="!collapsed" class="g3-nav-content">
|
||||
<ul class="g3-list-with-children">
|
||||
<G3SidebarItem
|
||||
v-for="(child, i) in item.items"
|
||||
:key="`${i}-${child.text}`"
|
||||
:item="child"
|
||||
:level="level + 1"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- 无子项:li.item > a.link -->
|
||||
<li v-else class="g3-item">
|
||||
<a
|
||||
:class="linkClass"
|
||||
:href="item.link"
|
||||
:rel="item.rel"
|
||||
:target="item.target"
|
||||
:aria-current="isActiveLink ? 'page' : undefined"
|
||||
>
|
||||
<component
|
||||
:is="iconComponent"
|
||||
v-if="iconComponent"
|
||||
class="g3-nav-icon"
|
||||
:size="16"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span class="g3-nav-title">{{ item.text }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
Reference in new issue
Block a user