@wot-ui/vitepress-theme 2.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +153 -0
  2. package/dist/config.js +118 -0
  3. package/dist/index.js +68 -0
  4. package/dist/locales/md-component-links.js +15 -0
  5. package/dist/plugins/md-component-links.js +34 -0
  6. package/dist/plugins/md-scss-vars.js +73 -0
  7. package/dist/plugins/md-version-badge.js +51 -0
  8. package/dist/plugins/virtual-version-data.js +83 -0
  9. package/dist/src/config.d.ts +3 -0
  10. package/dist/src/index.d.ts +21 -0
  11. package/dist/src/locales/md-component-links.d.ts +13 -0
  12. package/dist/src/plugins/md-component-links.d.ts +3 -0
  13. package/dist/src/plugins/md-scss-vars.d.ts +3 -0
  14. package/dist/src/plugins/md-version-badge.d.ts +6 -0
  15. package/dist/src/plugins/virtual-version-data.d.ts +3 -0
  16. package/dist/src/theme/composables/adSponsor.d.ts +30 -0
  17. package/dist/src/theme/composables/adsData.d.ts +16 -0
  18. package/dist/src/theme/composables/banner.d.ts +16 -0
  19. package/dist/src/theme/composables/cases.d.ts +16 -0
  20. package/dist/src/theme/composables/friendly.d.ts +19 -0
  21. package/dist/src/theme/composables/sponsor.d.ts +3 -0
  22. package/dist/src/theme/composables/team.d.ts +28 -0
  23. package/dist/src/theme/options.d.ts +3 -0
  24. package/dist/src/types.d.ts +86 -0
  25. package/dist/theme/Layout.vue +45 -0
  26. package/dist/theme/components/AsideSponsors.vue +105 -0
  27. package/dist/theme/components/Banner.vue +377 -0
  28. package/dist/theme/components/CustomFooter.vue +123 -0
  29. package/dist/theme/components/ExternalLink.vue +36 -0
  30. package/dist/theme/components/HomeCases.vue +122 -0
  31. package/dist/theme/components/HomeFriendly.vue +96 -0
  32. package/dist/theme/components/HomeTeam.vue +250 -0
  33. package/dist/theme/components/QrCode.vue +45 -0
  34. package/dist/theme/components/SidebarAds.vue +86 -0
  35. package/dist/theme/components/SpecialSponsor.vue +115 -0
  36. package/dist/theme/components/SvgImage.vue +22 -0
  37. package/dist/theme/components/VPContent.vue +92 -0
  38. package/dist/theme/components/VPDoc.vue +222 -0
  39. package/dist/theme/components/VPFeature.vue +150 -0
  40. package/dist/theme/components/VPIframe.vue +445 -0
  41. package/dist/theme/components/VPLocalNav.vue +151 -0
  42. package/dist/theme/components/VPNavBar.vue +253 -0
  43. package/dist/theme/components/VPSidebar.vue +120 -0
  44. package/dist/theme/components/VPSidebarItem.vue +271 -0
  45. package/dist/theme/components/WwAds.vue +74 -0
  46. package/dist/theme/composables/adSponsor.js +29 -0
  47. package/dist/theme/composables/adsData.js +35 -0
  48. package/dist/theme/composables/banner.js +35 -0
  49. package/dist/theme/composables/cases.js +43 -0
  50. package/dist/theme/composables/friendly.js +35 -0
  51. package/dist/theme/composables/sponsor.js +35 -0
  52. package/dist/theme/composables/team.js +48 -0
  53. package/dist/theme/options.js +4 -0
  54. package/dist/theme/styles/custom.css +206 -0
  55. package/dist/theme/styles/vars.css +136 -0
  56. package/dist/types.js +0 -0
  57. package/package.json +41 -0
@@ -0,0 +1,253 @@
1
+ <script lang="ts" setup>
2
+ import { useWindowScroll } from '@vueuse/core'
3
+ import { ref, watchPostEffect } from 'vue'
4
+ import VPNavBarAppearance from 'vitepress/dist/client/theme-default/components/VPNavBarAppearance.vue'
5
+ import VPNavBarExtra from 'vitepress/dist/client/theme-default/components/VPNavBarExtra.vue'
6
+ import VPNavBarHamburger from 'vitepress/dist/client/theme-default/components/VPNavBarHamburger.vue'
7
+ import VPNavBarMenu from 'vitepress/dist/client/theme-default/components/VPNavBarMenu.vue'
8
+ import VPNavBarSearch from 'vitepress/dist/client/theme-default/components/VPNavBarSearch.vue'
9
+ import VPNavBarSocialLinks from 'vitepress/dist/client/theme-default/components/VPNavBarSocialLinks.vue'
10
+ import VPNavBarTitle from 'vitepress/dist/client/theme-default/components/VPNavBarTitle.vue'
11
+ import VPNavBarTranslations from 'vitepress/dist/client/theme-default/components/VPNavBarTranslations.vue'
12
+ import { useLayout } from 'vitepress/theme'
13
+ import { useData } from 'vitepress'
14
+
15
+ const props = defineProps<{
16
+ isScreenOpen: boolean
17
+ }>()
18
+
19
+ defineEmits<{
20
+ (e: 'toggle-screen'): void
21
+ }>()
22
+
23
+ const { y } = useWindowScroll()
24
+ const { hasSidebar } = useLayout()
25
+ const { frontmatter } = useData()
26
+
27
+ const classes = ref<Record<string, boolean>>({})
28
+
29
+ watchPostEffect(() => {
30
+ classes.value = {
31
+ 'has-sidebar': hasSidebar.value,
32
+ home: frontmatter.value.layout === 'home',
33
+ top: y.value === 0,
34
+ 'screen-open': props.isScreenOpen
35
+ }
36
+ })
37
+ </script>
38
+
39
+ <template>
40
+ <div class="VPNavBar" :class="classes">
41
+ <div class="wrapper">
42
+ <div class="container">
43
+ <div class="title">
44
+ <VPNavBarTitle>
45
+ <template #nav-bar-title-before><slot name="nav-bar-title-before" /></template>
46
+ <template #nav-bar-title-after><slot name="nav-bar-title-after" /></template>
47
+ </VPNavBarTitle>
48
+ </div>
49
+
50
+ <div class="content">
51
+ <div class="content-body">
52
+ <slot name="nav-bar-content-before" />
53
+ <VPNavBarSearch class="search" />
54
+ <VPNavBarMenu class="menu" />
55
+ <VPNavBarTranslations class="translations" />
56
+ <VPNavBarAppearance class="appearance" />
57
+ <VPNavBarSocialLinks class="social-links" />
58
+ <VPNavBarExtra class="extra" />
59
+ <slot name="nav-bar-content-after" />
60
+ <VPNavBarHamburger class="hamburger" :active="isScreenOpen" @click="$emit('toggle-screen')" />
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="divider">
67
+ <div class="divider-line" />
68
+ </div>
69
+ </div>
70
+ </template>
71
+
72
+ <style scoped>
73
+ .VPNavBar {
74
+ position: relative;
75
+ height: var(--vp-nav-height);
76
+ pointer-events: none;
77
+ white-space: nowrap;
78
+ transition: background-color 0.25s;
79
+ }
80
+
81
+ .VPNavBar.screen-open {
82
+ transition: none;
83
+ background-color: var(--vp-nav-bg-color);
84
+ border-bottom: 1px solid var(--vp-c-divider);
85
+ }
86
+
87
+ .VPNavBar:not(.home) {
88
+ background-color: var(--vp-nav-bg-color);
89
+ }
90
+
91
+ @media (min-width: 960px) {
92
+ .VPNavBar:not(.home) {
93
+ background-color: transparent;
94
+ }
95
+
96
+ .VPNavBar:not(.has-sidebar):not(.home.top) {
97
+ background-color: var(--vp-nav-bg-color);
98
+ }
99
+ }
100
+
101
+ .wrapper {
102
+ padding: 0 8px 0 24px;
103
+ }
104
+
105
+ @media (min-width: 768px) {
106
+ .wrapper {
107
+ padding: 0 32px;
108
+ }
109
+ }
110
+
111
+ @media (min-width: 960px) {
112
+ .VPNavBar.has-sidebar .wrapper {
113
+ padding: 0;
114
+ }
115
+ }
116
+
117
+ .container {
118
+ display: flex;
119
+ justify-content: space-between;
120
+ margin: 0 auto;
121
+ height: var(--vp-nav-height);
122
+ pointer-events: none;
123
+ }
124
+
125
+ .container > .title,
126
+ .container > .content {
127
+ pointer-events: none;
128
+ }
129
+
130
+ .container :deep(*) {
131
+ pointer-events: auto;
132
+ }
133
+
134
+ @media (min-width: 960px) {
135
+ .VPNavBar.has-sidebar .container {
136
+ max-width: 100%;
137
+ }
138
+ }
139
+
140
+ .title {
141
+ flex-shrink: 0;
142
+ height: calc(var(--vp-nav-height) - 1px);
143
+ transition: background-color 0.5s;
144
+ }
145
+
146
+ @media (min-width: 960px) {
147
+ .VPNavBar.has-sidebar .title {
148
+ position: absolute;
149
+ top: 0;
150
+ left: 0;
151
+ z-index: 2;
152
+ padding: 0 32px;
153
+ width: var(--vp-sidebar-width);
154
+ height: var(--vp-nav-height);
155
+ background-color: transparent;
156
+ }
157
+ }
158
+
159
+ .content {
160
+ flex-grow: 1;
161
+ }
162
+
163
+ @media (min-width: 960px) {
164
+ .VPNavBar.has-sidebar .content {
165
+ position: relative;
166
+ z-index: 1;
167
+ padding-right: 32px;
168
+ padding-left: var(--vp-sidebar-width);
169
+ }
170
+ }
171
+
172
+ .content-body {
173
+ display: flex;
174
+ justify-content: flex-end;
175
+ align-items: center;
176
+ height: var(--vp-nav-height);
177
+ transition: background-color 0.5s;
178
+ }
179
+
180
+ @media (min-width: 960px) {
181
+ .VPNavBar:not(.home.top) .content-body {
182
+ position: relative;
183
+ background-color: var(--vp-nav-bg-color);
184
+ }
185
+
186
+ .VPNavBar:not(.has-sidebar):not(.home.top) .content-body {
187
+ background-color: transparent;
188
+ }
189
+ }
190
+
191
+ @media (max-width: 767px) {
192
+ .content-body {
193
+ column-gap: 0.5rem;
194
+ }
195
+ }
196
+
197
+ .menu + .translations::before,
198
+ .menu + .appearance::before,
199
+ .menu + .social-links::before,
200
+ .translations + .appearance::before,
201
+ .appearance + .social-links::before {
202
+ margin-right: 8px;
203
+ margin-left: 8px;
204
+ width: 1px;
205
+ height: 24px;
206
+ background-color: var(--vp-c-divider);
207
+ content: '';
208
+ }
209
+
210
+ .menu + .appearance::before,
211
+ .translations + .appearance::before {
212
+ margin-right: 16px;
213
+ }
214
+
215
+ .appearance + .social-links::before {
216
+ margin-left: 16px;
217
+ }
218
+
219
+ .social-links {
220
+ margin-right: -8px;
221
+ }
222
+
223
+ .divider {
224
+ width: 100%;
225
+ height: 1px;
226
+ }
227
+
228
+ @media (min-width: 960px) {
229
+ .VPNavBar.has-sidebar .divider {
230
+ padding-left: var(--vp-sidebar-width);
231
+ }
232
+ }
233
+
234
+ .divider-line {
235
+ width: 100%;
236
+ height: 1px;
237
+ transition: background-color 0.5s;
238
+ }
239
+
240
+ .VPNavBar:not(.home) .divider-line {
241
+ background-color: var(--vp-c-gutter);
242
+ }
243
+
244
+ @media (min-width: 960px) {
245
+ .VPNavBar:not(.home.top) .divider-line {
246
+ background-color: var(--vp-c-gutter);
247
+ }
248
+
249
+ .VPNavBar:not(.has-sidebar):not(.home.top) .divider {
250
+ background-color: var(--vp-c-gutter);
251
+ }
252
+ }
253
+ </style>
@@ -0,0 +1,120 @@
1
+ <script lang="ts" setup>
2
+ import { useScrollLock } from '@vueuse/core'
3
+ import { inBrowser } from 'vitepress'
4
+ import { ref, watch } from 'vue'
5
+ import VPSidebarGroup from 'vitepress/dist/client/theme-default/components/VPSidebarGroup.vue'
6
+ import { useLayout } from 'vitepress/theme'
7
+ import SidebarAds from './SidebarAds.vue'
8
+
9
+ const { sidebarGroups, hasSidebar } = useLayout()
10
+
11
+ const props = defineProps<{
12
+ open: boolean
13
+ }>()
14
+
15
+ // a11y: focus Nav element when menu has opened
16
+ const navEl = ref<HTMLElement | null>(null)
17
+ const isLocked = useScrollLock(inBrowser ? document.body : null)
18
+
19
+ watch(
20
+ [props, navEl],
21
+ () => {
22
+ if (props.open) {
23
+ isLocked.value = true
24
+ navEl.value?.focus()
25
+ } else isLocked.value = false
26
+ },
27
+ { immediate: true, flush: 'post' }
28
+ )
29
+
30
+ const key = ref(0)
31
+
32
+ watch(
33
+ sidebarGroups,
34
+ () => {
35
+ key.value += 1
36
+ },
37
+ { deep: true }
38
+ )
39
+ </script>
40
+
41
+ <template>
42
+ <aside v-if="hasSidebar" class="VPSidebar" :class="{ open }" ref="navEl" @click.stop>
43
+ <div class="curtain" />
44
+
45
+ <nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1">
46
+ <span class="visually-hidden" id="sidebar-aria-label">Sidebar Navigation</span>
47
+
48
+ <slot name="sidebar-nav-before" />
49
+ <!-- 添加广告位插槽 -->
50
+ <slot name="sidebar-ad">
51
+ <SidebarAds />
52
+ </slot>
53
+ <VPSidebarGroup :items="sidebarGroups" :key="key" />
54
+ <slot name="sidebar-nav-after" />
55
+ </nav>
56
+ </aside>
57
+ </template>
58
+
59
+ <style scoped>
60
+ .VPSidebar {
61
+ position: fixed;
62
+ top: var(--vp-layout-top-height, 0px);
63
+ bottom: 0;
64
+ left: 0;
65
+ z-index: var(--vp-z-index-sidebar);
66
+ padding: 32px 32px 96px;
67
+ width: var(--vp-sidebar-width);
68
+ background-color: var(--vp-sidebar-bg-color);
69
+ opacity: 0;
70
+ box-shadow: var(--vp-c-shadow-3);
71
+ overflow-x: hidden;
72
+ overflow-y: auto;
73
+ transform: translateX(-100%);
74
+ transition: opacity 0.5s, transform 0.25s ease;
75
+ overscroll-behavior: contain;
76
+ scrollbar-gutter: stable both-edges;
77
+ }
78
+
79
+ .VPSidebar.open {
80
+ opacity: 1;
81
+ visibility: visible;
82
+ transform: translateX(0);
83
+ transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
84
+ }
85
+
86
+ .dark .VPSidebar {
87
+ box-shadow: var(--vp-shadow-1);
88
+ }
89
+
90
+ @media (min-width: 960px) {
91
+ .VPSidebar {
92
+ padding-top: var(--vp-nav-height);
93
+ width: var(--vp-sidebar-width);
94
+ max-width: 100%;
95
+ background-color: var(--vp-sidebar-bg-color);
96
+ opacity: 1;
97
+ visibility: visible;
98
+ box-shadow: none;
99
+ transform: translateX(0);
100
+ }
101
+ }
102
+
103
+ @media (min-width: 960px) {
104
+ .curtain {
105
+ position: sticky;
106
+ top: -64px;
107
+ left: 0;
108
+ z-index: 1;
109
+ margin-top: calc(var(--vp-nav-height) * -1);
110
+ margin-right: -32px;
111
+ margin-left: -32px;
112
+ height: var(--vp-nav-height);
113
+ background-color: var(--vp-sidebar-bg-color);
114
+ }
115
+ }
116
+
117
+ .nav {
118
+ outline: 0;
119
+ }
120
+ </style>
@@ -0,0 +1,271 @@
1
+ <script setup lang="ts">
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
+ import { computed } from 'vue'
4
+ import { useSidebarItemControl } from 'vitepress/dist/client/theme-default/composables/sidebar.js'
5
+ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
6
+ import { versionData } from 'virtual:wot-vitepress-theme/version-data'
7
+
8
+ const props = defineProps<{
9
+ item: DefaultTheme.SidebarItem
10
+ depth: number
11
+ }>()
12
+
13
+ const { collapsed, collapsible, isLink, isActiveLink, hasActiveLink, hasChildren, toggle } = useSidebarItemControl(computed(() => props.item))
14
+
15
+ const sectionTag = computed(() => (hasChildren.value ? 'section' : 'div'))
16
+
17
+ const linkTag = computed(() => (isLink.value ? 'a' : 'div'))
18
+
19
+ const textTag = computed(() => {
20
+ return !hasChildren.value ? 'p' : props.depth + 2 === 7 ? 'p' : `h${props.depth + 2}`
21
+ })
22
+
23
+ const itemRole = computed(() => (isLink.value ? undefined : 'button'))
24
+
25
+ const classes = computed(() => [
26
+ [`level-${props.depth}`],
27
+ { collapsible: collapsible.value },
28
+ { collapsed: collapsed.value },
29
+ { 'is-link': isLink.value },
30
+ { 'is-active': isActiveLink.value },
31
+ { 'has-active': hasActiveLink.value }
32
+ ])
33
+
34
+ // 获取版本信息
35
+ const versionInfo = computed(() => {
36
+ if (!props.item.link) return null
37
+
38
+ // 从链接中提取路径
39
+ const path = props.item.link
40
+ const version = versionData[path]
41
+
42
+ if (!version) return null
43
+
44
+ return {
45
+ text: version,
46
+ type: 'warning' // 统一使用warning类型(橙色)
47
+ }
48
+ })
49
+
50
+ function onItemInteraction(e: MouseEvent | Event) {
51
+ if ('key' in e && e.key !== 'Enter') {
52
+ return
53
+ }
54
+ !props.item.link && toggle()
55
+ }
56
+
57
+ function onCaretClick() {
58
+ props.item.link && toggle()
59
+ }
60
+ </script>
61
+
62
+ <template>
63
+ <component :is="sectionTag" class="VPSidebarItem" :class="classes">
64
+ <div
65
+ v-if="item.text"
66
+ class="item"
67
+ :role="itemRole"
68
+ v-on="item.items ? { click: onItemInteraction, keydown: onItemInteraction } : {}"
69
+ :tabindex="item.items && 0"
70
+ >
71
+ <div class="indicator" />
72
+
73
+ <VPLink v-if="item.link" :tag="linkTag" class="link" :href="item.link" :rel="item.rel" :target="item.target">
74
+ <component :is="textTag" class="text">
75
+ {{ item.text }}
76
+ <el-tag v-if="versionInfo" size="small" effect="plain" round class="version-tag">
77
+ {{ versionInfo.text }}
78
+ </el-tag>
79
+ </component>
80
+ </VPLink>
81
+ <component v-else :is="textTag" class="text">
82
+ {{ item.text }}
83
+ <el-tag v-if="versionInfo" size="small" effect="plain" round class="version-tag">
84
+ {{ versionInfo.text }}
85
+ </el-tag>
86
+ </component>
87
+
88
+ <div
89
+ v-if="item.collapsed != null && item.items && item.items.length"
90
+ class="caret"
91
+ role="button"
92
+ aria-label="toggle section"
93
+ @click="onCaretClick"
94
+ @keydown.enter="onCaretClick"
95
+ tabindex="0"
96
+ >
97
+ <span class="vpi-chevron-right caret-icon" />
98
+ </div>
99
+ </div>
100
+
101
+ <div v-if="item.items && item.items.length" class="items">
102
+ <template v-if="depth < 5">
103
+ <VPSidebarItem v-for="i in item.items" :key="i.text" :item="i" :depth="depth + 1" />
104
+ </template>
105
+ </div>
106
+ </component>
107
+ </template>
108
+
109
+ <style scoped>
110
+ .VPSidebarItem.level-0 {
111
+ padding-bottom: 24px;
112
+ }
113
+
114
+ .VPSidebarItem.collapsed.level-0 {
115
+ padding-bottom: 10px;
116
+ }
117
+
118
+ .item {
119
+ position: relative;
120
+ display: flex;
121
+ width: 100%;
122
+ }
123
+
124
+ .VPSidebarItem.collapsible > .item {
125
+ cursor: pointer;
126
+ }
127
+
128
+ .indicator {
129
+ position: absolute;
130
+ top: 6px;
131
+ bottom: 6px;
132
+ left: -17px;
133
+ width: 2px;
134
+ border-radius: 2px;
135
+ transition: background-color 0.25s;
136
+ }
137
+
138
+ .VPSidebarItem.level-2.is-active > .item > .indicator,
139
+ .VPSidebarItem.level-3.is-active > .item > .indicator,
140
+ .VPSidebarItem.level-4.is-active > .item > .indicator,
141
+ .VPSidebarItem.level-5.is-active > .item > .indicator {
142
+ background-color: var(--vp-c-brand-1);
143
+ }
144
+
145
+ .link {
146
+ display: flex;
147
+ align-items: center;
148
+ flex-grow: 1;
149
+ }
150
+
151
+ .text {
152
+ flex-grow: 1;
153
+ padding: 4px 0;
154
+ line-height: 24px;
155
+ font-size: 14px;
156
+ transition: color 0.25s;
157
+ display: flex;
158
+ align-items: center;
159
+ gap: 8px;
160
+ }
161
+
162
+ .VPSidebarItem.level-0 .text {
163
+ font-weight: 700;
164
+ color: var(--vp-c-text-1);
165
+ }
166
+
167
+ .VPSidebarItem.level-1 .text,
168
+ .VPSidebarItem.level-2 .text,
169
+ .VPSidebarItem.level-3 .text,
170
+ .VPSidebarItem.level-4 .text,
171
+ .VPSidebarItem.level-5 .text {
172
+ font-weight: 500;
173
+ color: var(--vp-c-text-2);
174
+ }
175
+
176
+ .VPSidebarItem.level-0.is-link > .item > .link:hover .text,
177
+ .VPSidebarItem.level-1.is-link > .item > .link:hover .text,
178
+ .VPSidebarItem.level-2.is-link > .item > .link:hover .text,
179
+ .VPSidebarItem.level-3.is-link > .item > .link:hover .text,
180
+ .VPSidebarItem.level-4.is-link > .item > .link:hover .text,
181
+ .VPSidebarItem.level-5.is-link > .item > .link:hover .text {
182
+ color: var(--vp-c-brand-1);
183
+ }
184
+
185
+ .VPSidebarItem.level-0.has-active > .item > .text,
186
+ .VPSidebarItem.level-1.has-active > .item > .text,
187
+ .VPSidebarItem.level-2.has-active > .item > .text,
188
+ .VPSidebarItem.level-3.has-active > .item > .text,
189
+ .VPSidebarItem.level-4.has-active > .item > .text,
190
+ .VPSidebarItem.level-5.has-active > .item > .text,
191
+ .VPSidebarItem.level-0.has-active > .item > .link > .text,
192
+ .VPSidebarItem.level-1.has-active > .item > .link > .text,
193
+ .VPSidebarItem.level-2.has-active > .item > .link > .text,
194
+ .VPSidebarItem.level-3.has-active > .item > .link > .text,
195
+ .VPSidebarItem.level-4.has-active > .item > .link > .text,
196
+ .VPSidebarItem.level-5.has-active > .item > .link > .text {
197
+ color: var(--vp-c-text-1);
198
+ }
199
+
200
+ .VPSidebarItem.level-0.is-active > .item .link > .text,
201
+ .VPSidebarItem.level-1.is-active > .item .link > .text,
202
+ .VPSidebarItem.level-2.is-active > .item .link > .text,
203
+ .VPSidebarItem.level-3.is-active > .item .link > .text,
204
+ .VPSidebarItem.level-4.is-active > .item .link > .text,
205
+ .VPSidebarItem.level-5.is-active > .item .link > .text {
206
+ color: var(--vp-c-brand-1);
207
+ }
208
+
209
+ .caret {
210
+ display: flex;
211
+ justify-content: center;
212
+ align-items: center;
213
+ margin-right: -7px;
214
+ width: 32px;
215
+ height: 32px;
216
+ color: var(--vp-c-text-3);
217
+ cursor: pointer;
218
+ transition: color 0.25s;
219
+ flex-shrink: 0;
220
+ }
221
+
222
+ .item:hover .caret {
223
+ color: var(--vp-c-text-2);
224
+ }
225
+
226
+ .item:hover .caret:hover {
227
+ color: var(--vp-c-text-1);
228
+ }
229
+
230
+ .caret-icon {
231
+ font-size: 18px;
232
+ /*rtl:ignore*/
233
+ transform: rotate(90deg);
234
+ transition: transform 0.25s;
235
+ }
236
+
237
+ .VPSidebarItem.collapsed .caret-icon {
238
+ transform: rotate(0) /*rtl:rotate(180deg)*/;
239
+ }
240
+
241
+ .VPSidebarItem.level-1 .items,
242
+ .VPSidebarItem.level-2 .items,
243
+ .VPSidebarItem.level-3 .items,
244
+ .VPSidebarItem.level-4 .items,
245
+ .VPSidebarItem.level-5 .items {
246
+ border-left: 1px solid var(--vp-c-divider);
247
+ padding-left: 16px;
248
+ }
249
+
250
+ .VPSidebarItem.collapsed .items {
251
+ display: none;
252
+ }
253
+
254
+ /* 版本标签样式 */
255
+ .version-tag {
256
+ margin-left: 4px;
257
+ flex-shrink: 0;
258
+ }
259
+
260
+ /* 深色模式适配 */
261
+ :root.dark .version-tag {
262
+ opacity: 0.9;
263
+ }
264
+
265
+ /* 响应式设计 */
266
+ @media (max-width: 960px) {
267
+ .version-tag {
268
+ font-size: 10px;
269
+ }
270
+ }
271
+ </style>