vitepress 1.0.0-draft.4 → 1.0.0-draft.7

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 (67) hide show
  1. package/README.md +3 -1
  2. package/bin/vitepress.js +1 -1
  3. package/dist/client/app/index.js +1 -5
  4. package/dist/client/index.d.ts +123 -137
  5. package/dist/client/index.js +1 -2
  6. package/dist/client/theme-default/Layout.vue +7 -0
  7. package/dist/client/theme-default/NotFound.vue +74 -14
  8. package/dist/client/theme-default/components/VPBox.vue +2 -6
  9. package/dist/client/theme-default/components/VPButton.vue +0 -1
  10. package/dist/client/theme-default/components/VPCarbonAds.vue +90 -0
  11. package/dist/client/theme-default/components/VPContent.vue +11 -1
  12. package/dist/client/theme-default/components/VPDoc.vue +29 -35
  13. package/dist/client/theme-default/components/VPDocAside.vue +46 -0
  14. package/dist/client/theme-default/components/VPDocAsideCarbonAds.vue +13 -0
  15. package/dist/client/theme-default/components/{VPDocOutline.vue → VPDocAsideOutline.vue} +39 -34
  16. package/dist/client/theme-default/components/VPDocAsideSponsors.vue +32 -0
  17. package/dist/client/theme-default/components/VPDocFooter.vue +1 -1
  18. package/dist/client/theme-default/components/VPFlyout.vue +2 -3
  19. package/dist/client/theme-default/components/VPFooter.vue +1 -1
  20. package/dist/client/theme-default/components/VPHero.vue +170 -29
  21. package/dist/client/theme-default/components/VPHomeFeatures.vue +1 -0
  22. package/dist/client/theme-default/components/VPHomeHero.vue +1 -0
  23. package/dist/client/theme-default/components/VPHomeSponsors.vue +3 -3
  24. package/dist/client/theme-default/components/VPLink.vue +2 -1
  25. package/dist/client/theme-default/components/VPLocalNav.vue +1 -1
  26. package/dist/client/theme-default/components/VPMenu.vue +9 -14
  27. package/dist/client/theme-default/components/VPMenuLink.vue +10 -4
  28. package/dist/client/theme-default/components/VPNav.vue +18 -1
  29. package/dist/client/theme-default/components/VPNavBar.vue +19 -7
  30. package/dist/client/theme-default/components/VPNavBarExtra.vue +20 -45
  31. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +2 -8
  32. package/dist/client/theme-default/components/VPNavBarMenuLink.vue +3 -3
  33. package/dist/client/theme-default/components/VPNavBarSearch.vue +6 -6
  34. package/dist/client/theme-default/components/VPNavBarTitle.vue +4 -2
  35. package/dist/client/theme-default/components/VPNavBarTranslations.vue +10 -39
  36. package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +1 -2
  37. package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +1 -1
  38. package/dist/client/theme-default/components/VPSidebar.vue +10 -4
  39. package/dist/client/theme-default/components/VPSidebarGroup.vue +80 -17
  40. package/dist/client/theme-default/components/VPSidebarLink.vue +2 -9
  41. package/dist/client/theme-default/components/VPSocialLink.vue +2 -2
  42. package/dist/client/theme-default/components/VPSocialLinks.vue +1 -1
  43. package/dist/client/theme-default/components/VPSponsors.vue +15 -40
  44. package/dist/client/theme-default/components/VPSponsorsGrid.vue +2 -2
  45. package/dist/client/theme-default/components/icons/VPIconMinus.vue +5 -0
  46. package/dist/client/theme-default/components/icons/VPIconMinusSquare.vue +6 -0
  47. package/dist/client/theme-default/components/icons/VPIconPlusSquare.vue +6 -0
  48. package/dist/client/theme-default/composables/aside.js +17 -0
  49. package/dist/client/theme-default/composables/copy-code.js +33 -0
  50. package/dist/client/theme-default/composables/outline.js +3 -3
  51. package/dist/client/theme-default/composables/sponsor-grid.js +8 -6
  52. package/dist/client/theme-default/index.js +1 -0
  53. package/dist/client/theme-default/styles/base.css +13 -1
  54. package/dist/client/theme-default/styles/components/custom-block.css +2 -2
  55. package/dist/client/theme-default/styles/components/vp-doc.css +98 -107
  56. package/dist/client/theme-default/styles/components/vp-sponsor.css +51 -7
  57. package/dist/client/theme-default/styles/vars.css +42 -27
  58. package/dist/node/cli.js +32 -31
  59. package/dist/node/index.d.ts +371 -364
  60. package/dist/node/index.js +22 -37
  61. package/dist/node/serve-9c85885c.js +64795 -0
  62. package/dist/node-cjs/cli.cjs +304 -0
  63. package/dist/node-cjs/index.cjs +38 -0
  64. package/dist/{node/serve-b3182d88.js → node-cjs/serve-a73b4871.cjs} +27419 -28634
  65. package/package.json +46 -38
  66. package/theme.d.ts +7 -2
  67. package/types/default-theme.d.ts +15 -2
@@ -3,13 +3,13 @@ import VPIconHeart from './icons/VPIconHeart.vue'
3
3
  import VPButton from './VPButton.vue'
4
4
  import VPSponsors from './VPSponsors.vue'
5
5
 
6
- interface Sponsors {
6
+ export interface Sponsors {
7
7
  tier: string
8
8
  size?: 'medium' | 'big'
9
9
  items: Sponsor[]
10
10
  }
11
11
 
12
- interface Sponsor {
12
+ export interface Sponsor {
13
13
  name: string
14
14
  img: string
15
15
  url: string
@@ -50,7 +50,7 @@ defineProps<{
50
50
  .VPHomeSponsors {
51
51
  border-top: 1px solid var(--vp-c-divider-light);
52
52
  padding: 88px 24px 96px;
53
- background-color: var(--vp-c-bg-content);
53
+ background-color: var(--vp-c-bg);
54
54
  }
55
55
 
56
56
  .container {
@@ -1,5 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { computed } from 'vue'
3
+ import { normalizeLink } from '../support/utils'
3
4
  import VPIconExternalLink from './icons/VPIconExternalLink.vue'
4
5
 
5
6
  const props = defineProps<{
@@ -15,7 +16,7 @@ const isExternal = computed(() => props.href && /^[a-z]+:/i.test(props.href))
15
16
  :is="href ? 'a' : 'span'"
16
17
  class="VPLink"
17
18
  :class="{ link: href }"
18
- :href="href"
19
+ :href="href ? normalizeLink(href) : undefined"
19
20
  :target="isExternal ? '_blank' : undefined"
20
21
  :rel="isExternal ? 'noopener noreferrer' : undefined"
21
22
  >
@@ -45,7 +45,7 @@ function scrollToTop() {
45
45
  justify-content: space-between;
46
46
  border-bottom: 1px solid var(--vp-c-divider-light);
47
47
  width: 100%;
48
- background-color: var(--vp-c-bg-content);
48
+ background-color: var(--vp-c-bg);
49
49
  transition: border-color 0.5s, background-color 0.5s;
50
50
  }
51
51
 
@@ -22,32 +22,27 @@ defineProps<{
22
22
 
23
23
  <style scoped>
24
24
  .VPMenu {
25
- border-radius: 8px;
26
- padding: 12px 0;
27
- min-width: 192px;
28
- border: 1px solid transparent;
29
- background: var(--vp-c-bg);
25
+ border-radius: 12px;
26
+ padding: 12px;
27
+ min-width: 128px;
28
+ border: 1px solid var(--vp-c-divider-light);
29
+ background-color: var(--vp-c-bg);
30
30
  box-shadow: var(--vp-shadow-3);
31
31
  transition: background-color 0.5s;
32
32
  }
33
33
 
34
34
  .dark .VPMenu {
35
- background: var(--vp-c-bg);
36
- box-shadow: var(--vp-shadow-1);
37
- border: 1px solid var(--vp-c-divider-light);
38
- }
39
-
40
- .VPMenu :deep(.items) {
41
- transition: border-color .5s;
35
+ box-shadow: var(--vp-shadow-2);
42
36
  }
43
37
 
44
38
  .VPMenu :deep(.group) {
45
- padding: 0 0 12px;
39
+ margin: 0 -12px;
40
+ padding: 0 12px 12px;
46
41
  }
47
42
 
48
43
  .VPMenu :deep(.group + .group) {
49
44
  border-top: 1px solid var(--vp-c-divider-light);
50
- padding: 11px 0 12px;
45
+ padding: 11px 12px 12px;
51
46
  }
52
47
 
53
48
  .VPMenu :deep(.group:last-child) {
@@ -15,16 +15,22 @@ defineProps<{
15
15
  <style scoped>
16
16
  .VPMenuLink {
17
17
  display: block;
18
- padding: 0 16px;
19
- line-height: 28px;
20
- font-size: 13px;
18
+ border-radius: 6px;
19
+ padding: 0 12px;
20
+ line-height: 32px;
21
+ font-size: 14px;
21
22
  font-weight: 500;
22
23
  color: var(--vp-c-text-1);
23
24
  white-space: nowrap;
24
- transition: color 0.25s;
25
+ transition: background-color 0.25s, color 0.25s;
25
26
  }
26
27
 
27
28
  .VPMenuLink:hover {
28
29
  color: var(--vp-c-brand);
30
+ background-color: var(--vp-c-bg-mute);
31
+ }
32
+
33
+ .dark .VPMenuLink:hover {
34
+ background-color: var(--vp-c-bg-soft);
29
35
  }
30
36
  </style>
@@ -1,16 +1,18 @@
1
1
  <script setup lang="ts">
2
2
  import { provide } from 'vue'
3
3
  import { useNav } from '../composables/nav'
4
+ import { useSidebar } from '../composables/sidebar'
4
5
  import VPNavBar from './VPNavBar.vue'
5
6
  import VPNavScreen from './VPNavScreen.vue'
6
7
 
7
8
  const { isScreenOpen, closeScreen, toggleScreen } = useNav()
9
+ const { hasSidebar } = useSidebar()
8
10
 
9
11
  provide('close-screen', closeScreen)
10
12
  </script>
11
13
 
12
14
  <template>
13
- <header class="VPNav">
15
+ <header class="VPNav" :class="{ 'no-sidebar' : !hasSidebar }">
14
16
  <VPNavBar :is-screen-open="isScreenOpen" @toggle-screen="toggleScreen" />
15
17
  <VPNavScreen :open="isScreenOpen" />
16
18
  </header>
@@ -29,5 +31,20 @@ provide('close-screen', closeScreen)
29
31
  .VPNav {
30
32
  position: fixed;
31
33
  }
34
+
35
+ .VPNav.no-sidebar {
36
+ backdrop-filter: saturate(50%) blur(8px);
37
+ -webkit-backdrop-filter: saturate(50%) blur(8px);
38
+ }
39
+
40
+ @supports not (backdrop-filter: saturate(50%) blur(8px)) {
41
+ .VPNav.no-sidebar {
42
+ background: rgba(255, 255, 255, 0.95);
43
+ }
44
+
45
+ .dark .VPNav.no-sidebar {
46
+ background: rgba(36, 36, 36, 0.95);
47
+ }
48
+ }
32
49
  }
33
50
  </style>
@@ -1,4 +1,5 @@
1
1
  <script lang="ts" setup>
2
+ import { useSidebar } from '../composables/sidebar'
2
3
  import VPNavBarTitle from './VPNavBarTitle.vue'
3
4
  import VPNavBarSearch from './VPNavBarSearch.vue'
4
5
  import VPNavBarMenu from './VPNavBarMenu.vue'
@@ -15,10 +16,12 @@ defineProps<{
15
16
  defineEmits<{
16
17
  (e: 'toggle-screen'): void
17
18
  }>()
19
+
20
+ const { hasSidebar } = useSidebar()
18
21
  </script>
19
22
 
20
23
  <template>
21
- <div class="VPNavBar">
24
+ <div class="VPNavBar" :class="{ 'has-sidebar' : hasSidebar }">
22
25
  <div class="container">
23
26
  <VPNavBarTitle />
24
27
 
@@ -60,6 +63,21 @@ defineEmits<{
60
63
  height: var(--vp-nav-height-desktop);
61
64
  border-bottom: 0;
62
65
  }
66
+
67
+ .VPNavBar.has-sidebar .content {
68
+ backdrop-filter: saturate(50%) blur(8px);
69
+ -webkit-backdrop-filter: saturate(50%) blur(8px);
70
+ }
71
+
72
+ @supports not (backdrop-filter: saturate(50%) blur(8px)) {
73
+ .VPNavBar.has-sidebar.content {
74
+ background: rgba(255, 255, 255, 0.95);
75
+ }
76
+
77
+ .dark .VPNavBar.has-sidebar .content {
78
+ background: rgba(36, 36, 36, 0.95);
79
+ }
80
+ }
63
81
  }
64
82
 
65
83
  .container {
@@ -76,12 +94,6 @@ defineEmits<{
76
94
  flex-grow: 1;
77
95
  }
78
96
 
79
- @media (min-width: 960px) {
80
- .content {
81
- backdrop-filter: saturate(50%) blur(8px);
82
- }
83
- }
84
-
85
97
  .menu + .translations::before,
86
98
  .menu + .appearance::before,
87
99
  .menu + .social-links::before,
@@ -1,6 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
  import { useData } from 'vitepress'
3
3
  import VPFlyout from './VPFlyout.vue'
4
+ import VPMenuLink from './VPMenuLink.vue'
4
5
  import VPSwitchAppearance from './VPSwitchAppearance.vue'
5
6
  import VPSocialLinks from './VPSocialLinks.vue'
6
7
 
@@ -10,21 +11,15 @@ const { site, theme } = useData()
10
11
  <template>
11
12
  <VPFlyout class="VPNavBarExtra" label="extra navigation">
12
13
  <div v-if="theme.localeLinks" class="group">
13
- <div class="trans">
14
- <p class="trans-title">
15
- {{ theme.localeLinks.text }}
16
- </p>
14
+ <p class="trans-title">{{ theme.localeLinks.text }}</p>
17
15
 
18
- <ul class="trans-list">
19
- <li v-for="locale in theme.localeLinks.items" :key="locale.link" class="trans-item">
20
- <a class="trans-link" :href="locale.link">{{ locale.text }}</a>
21
- </li>
22
- </ul>
23
- </div>
16
+ <template v-for="locale in theme.localeLinks.items" :key="locale.link">
17
+ <VPMenuLink :item="locale" />
18
+ </template>
24
19
  </div>
25
20
 
26
21
  <div v-if="site.appearance" class="group">
27
- <div class="item">
22
+ <div class="item appearance">
28
23
  <p class="label">Appearance</p>
29
24
  <div class="appearance-action">
30
25
  <VPSwitchAppearance />
@@ -33,8 +28,8 @@ const { site, theme } = useData()
33
28
  </div>
34
29
 
35
30
  <div v-if="theme.socialLinks" class="group">
36
- <div class="item">
37
- <VPSocialLinks class="social-links" :links="theme.socialLinks" />
31
+ <div class="item social-links">
32
+ <VPSocialLinks class="social-links-list" :links="theme.socialLinks" />
38
33
  </div>
39
34
  </div>
40
35
  </VPFlyout>
@@ -58,50 +53,30 @@ const { site, theme } = useData()
58
53
  }
59
54
  }
60
55
 
61
- .trans {
62
- padding: 2px 16px 0;
63
- }
64
-
65
56
  .trans-title {
66
- display: flex;
67
- align-items: center;
68
- font-size: 13px;
69
- font-weight: 600;
70
- color: var(--vp-c-text-1);
71
- }
72
-
73
- .trans-icon {
74
- margin-right: 12px;
75
- width: 16px;
76
- height: 16px;
77
- fill: currentColor;
78
- }
79
-
80
- .trans-list {
81
- padding: 2px 0 0 0;
82
- }
83
-
84
- .trans-link {
85
- line-height: 28px;
86
- font-size: 13px;
57
+ padding: 0 24px 0 12px;
58
+ line-height: 32px;
59
+ font-size: 14px;
60
+ font-weight: 700;
87
61
  color: var(--vp-c-text-1);
88
- transition: color 0.25s;
89
62
  }
90
63
 
91
- .trans-link:hover {
92
- color: var(--vp-c-brand);
93
- }
94
-
95
- .item {
64
+ .item.appearance,
65
+ .item.social-links {
96
66
  display: flex;
97
67
  align-items: center;
68
+ padding: 0 12px;
69
+ }
70
+
71
+ .item.appearance {
72
+ min-width: 176px;
98
73
  }
99
74
 
100
75
  .appearance-action {
101
76
  margin-right: -2px;
102
77
  }
103
78
 
104
- .social-links {
79
+ .social-links-list {
105
80
  margin: -4px -8px;
106
81
  }
107
82
  </style>
@@ -1,18 +1,12 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme, useData } from 'vitepress'
3
- import { isActive } from '../support/utils'
2
+ import { DefaultTheme } from '../config'
4
3
  import VPFlyout from './VPFlyout.vue'
5
4
 
6
5
  defineProps<{
7
6
  item: DefaultTheme.NavItemWithChildren
8
7
  }>()
9
-
10
- const { page } = useData()
11
8
  </script>
12
9
 
13
10
  <template>
14
- <VPFlyout
15
- :button="item.text"
16
- :items="item.items"
17
- />
11
+ <VPFlyout :button="item.text" :items="item.items" />
18
12
  </template>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme, useData } from 'vitepress'
2
+ import { useData } from 'vitepress'
3
3
  import { isActive } from '../support/utils'
4
- import { NavItemWithLink } from '../config'
4
+ import { DefaultTheme } from '../config'
5
5
  import VPLink from './VPLink.vue'
6
6
 
7
7
  defineProps<{
@@ -34,7 +34,7 @@ const { page } = useData()
34
34
  align-items: center;
35
35
  padding: 0 12px;
36
36
  line-height: var(--vp-nav-height-mobile);
37
- font-size: 13px;
37
+ font-size: 14px;
38
38
  font-weight: 500;
39
39
  color: var(--vp-c-text-1);
40
40
  transition: color 0.25s;
@@ -1,11 +1,11 @@
1
1
  <script lang="ts" setup>
2
2
  import '@docsearch/css'
3
- import { useData } from 'vitepress'
4
3
  import { defineAsyncComponent, ref, onMounted, onUnmounted } from 'vue'
4
+ import { useData } from 'vitepress'
5
5
 
6
- const VPAlgoliaSearchBox = defineAsyncComponent(() => {
7
- return import('./VPAlgoliaSearchBox.vue')
8
- })
6
+ const VPAlgoliaSearchBox = __ALGOLIA__
7
+ ? defineAsyncComponent(() => import('./VPAlgoliaSearchBox.vue'))
8
+ : () => null
9
9
 
10
10
  const { theme } = useData()
11
11
 
@@ -161,12 +161,12 @@ function load() {
161
161
  padding: 0 10px 0 12px;
162
162
  width: 100%;
163
163
  height: 40px;
164
- background-color: var(--vp-c-bg-sidebar);
164
+ background-color: var(--vp-c-bg-alt);
165
165
  }
166
166
 
167
167
  .DocSearch-Button:hover {
168
168
  border-color: var(--vp-c-brand);
169
- background: var(--vp-c-bg-sidebar);
169
+ background: var(--vp-c-bg-alt);
170
170
  }
171
171
  }
172
172
 
@@ -18,14 +18,16 @@ const { hasSidebar } = useSidebar()
18
18
  <style scoped>
19
19
  .VPNavBarTitle {
20
20
  flex-shrink: 0;
21
+ border-bottom: 1px solid transparent;
22
+ transition: background-color 0.5s;
21
23
  }
22
24
 
23
25
  @media (min-width: 960px) {
24
26
  .VPNavBarTitle.has-sidebar {
25
27
  margin-right: 32px;
26
28
  width: calc(var(--vp-sidebar-width) - 64px);
27
- border-bottom: 1px solid var(--vp-c-divider-light);
28
- background-color: var(--vp-c-bg-sidebar);
29
+ border-bottom-color: var(--vp-c-divider-light);
30
+ background-color: var(--vp-c-bg-alt);
29
31
  }
30
32
  }
31
33
 
@@ -1,16 +1,10 @@
1
1
  <script lang="ts" setup>
2
- import { ref } from 'vue'
3
2
  import { useData } from 'vitepress'
4
3
  import VPIconLanguages from './icons/VPIconLanguages.vue'
5
4
  import VPFlyout from './VPFlyout.vue'
5
+ import VPMenuLink from './VPMenuLink.vue'
6
6
 
7
7
  const { theme } = useData()
8
-
9
- const isOpen = ref(false)
10
-
11
- function toggle() {
12
- isOpen.value = !isOpen.value
13
- }
14
8
  </script>
15
9
 
16
10
  <template>
@@ -19,16 +13,12 @@ function toggle() {
19
13
  class="VPNavBarTranslations"
20
14
  :icon="VPIconLanguages"
21
15
  >
22
- <div class="container">
23
- <p class="title">
24
- {{ theme.localeLinks.text }}
25
- </p>
16
+ <div class="items">
17
+ <p class="title">{{ theme.localeLinks.text }}</p>
26
18
 
27
- <ul class="list">
28
- <li v-for="locale in theme.localeLinks.items" :key="locale.link" class="lang">
29
- <a class="link" :href="locale.link">{{ locale.text }}</a>
30
- </li>
31
- </ul>
19
+ <template v-for="locale in theme.localeLinks.items" :key="locale.link">
20
+ <VPMenuLink :item="locale" />
21
+ </template>
32
22
  </div>
33
23
  </VPFlyout>
34
24
  </template>
@@ -45,30 +35,11 @@ function toggle() {
45
35
  }
46
36
  }
47
37
 
48
- .container {
49
- padding: 0 16px;
50
- }
51
-
52
38
  .title {
53
- display: flex;
54
- align-items: center;
55
- font-size: 13px;
56
- font-weight: 600;
57
- color: var(--vp-c-text-1);
58
- }
59
-
60
- .lang {
61
- padding: 4px 0 0 0;
62
- }
63
-
64
- .link {
65
- line-height: 28px;
66
- font-size: 13px;
39
+ padding: 0 24px 0 12px;
40
+ line-height: 32px;
41
+ font-size: 14px;
42
+ font-weight: 700;
67
43
  color: var(--vp-c-text-1);
68
- transition: color 0.25s;
69
- }
70
-
71
- .link:hover {
72
- color: var(--vp-c-brand);
73
44
  }
74
45
  </style>
@@ -1,13 +1,12 @@
1
1
  <script lang="ts" setup>
2
2
  import { computed, ref } from 'vue'
3
- import { DefaultTheme } from 'vitepress'
4
3
  import VPIconPlus from './icons/VPIconPlus.vue'
5
4
  import VPNavScreenMenuGroupLink from './VPNavScreenMenuGroupLink.vue'
6
5
  import VPNavScreenMenuGroupSection from './VPNavScreenMenuGroupSection.vue'
7
6
 
8
7
  const props = defineProps<{
9
8
  text: string
10
- items: DefaultTheme.NavItemChild[]
9
+ items: any[]
11
10
  }>()
12
11
 
13
12
  const isOpen = ref(false)
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme } from 'vitepress'
2
+ import { DefaultTheme } from '../config'
3
3
  import VPNavScreenMenuGroupLink from './VPNavScreenMenuGroupLink.vue'
4
4
 
5
5
  defineProps<{
@@ -34,7 +34,12 @@ watchPostEffect(async () => {
34
34
  </span>
35
35
 
36
36
  <div v-for="group in sidebar" :key="group.text" class="group">
37
- <VPSidebarGroup :text="group.text" :items="group.items" />
37
+ <VPSidebarGroup
38
+ :text="group.text"
39
+ :items="group.items"
40
+ :collapsible="group.collapsible"
41
+ :collapsed="group.collapsed"
42
+ />
38
43
  </div>
39
44
  </nav>
40
45
  </aside>
@@ -80,7 +85,7 @@ watchPostEffect(async () => {
80
85
  width: var(--vp-sidebar-width);
81
86
  max-width: 100%;
82
87
  width: var(--vp-sidebar-width);
83
- background-color: var(--vp-c-bg-sidebar);
88
+ background-color: var(--vp-c-bg-alt);
84
89
  opacity: 1;
85
90
  visibility: visible;
86
91
  box-shadow: none;
@@ -103,12 +108,13 @@ watchPostEffect(async () => {
103
108
  .group + .group {
104
109
  margin-top: 32px;
105
110
  border-top: 1px solid var(--vp-c-divider-light);
106
- padding-top: 8px;
111
+ padding-top: 10px;
107
112
  }
108
113
 
109
114
  @media (min-width: 960px) {
110
115
  .group {
111
- padding-top: 8px;
116
+ padding-top: 10px;
117
+ width: calc(var(--vp-sidebar-width) - 64px);
112
118
  }
113
119
 
114
120
  .group + .group {
@@ -1,44 +1,107 @@
1
1
  <script lang="ts" setup>
2
- import { useData } from 'vitepress'
2
+ import { ref } from 'vue'
3
3
  import { DefaultTheme } from '../config'
4
+ import VPIconPlusSquare from './icons/VPIconPlusSquare.vue'
5
+ import VPIconMinusSquare from './icons/VPIconMinusSquare.vue'
4
6
  import VPSidebarLink from './VPSidebarLink.vue'
5
7
 
6
8
  const props = defineProps<{
7
9
  text: string
8
10
  items: DefaultTheme.SidebarItem[]
11
+ collapsible?: boolean
12
+ collapsed?: boolean
9
13
  }>()
10
14
 
11
- const { page } = useData()
15
+ const collapsed = ref(props.collapsible && props.collapsed)
16
+
17
+ function toggle() {
18
+ if (props.collapsible) {
19
+ collapsed.value = !collapsed.value
20
+ }
21
+ }
12
22
  </script>
13
23
 
14
24
  <template>
15
- <section class="VPSidebarGroup">
16
- <div class="title">
25
+ <section class="VPSidebarGroup" :class="{ collapsible, collapsed }">
26
+ <div class="title" :role="collapsible ? 'button' : undefined" @click="toggle">
17
27
  <h2 class="title-text">{{ text }}</h2>
28
+ <div class="action">
29
+ <VPIconMinusSquare class="icon minus" />
30
+ <VPIconPlusSquare class="icon plus" />
31
+ </div>
18
32
  </div>
19
33
 
20
- <template v-for="item in items" :key="item.link">
21
- <VPSidebarLink :item="item" />
22
- </template>
34
+ <div class="items">
35
+ <template v-for="item in items" :key="item.link">
36
+ <VPSidebarLink :item="item" />
37
+ </template>
38
+ </div>
23
39
  </section>
24
40
  </template>
25
41
 
26
42
  <style scoped>
27
43
  .title {
28
- padding: 6px 0;
29
- }
30
-
31
- @media (min-width: 960px) {
32
- .title {
33
- padding: 4px 0;
34
- }
44
+ display: flex;
45
+ justify-content: space-between;
46
+ align-items: flex-start;
47
+ z-index: 2;
35
48
  }
36
49
 
37
50
  .title-text {
51
+ padding-top: 6px;
52
+ padding-bottom: 6px;
38
53
  line-height: 20px;
39
- font-size: 13px;
40
- font-weight: 600;
54
+ font-size: 14px;
55
+ font-weight: 700;
41
56
  color: var(--vp-c-text-1);
42
- transition: color 0.5s;
57
+ }
58
+
59
+ .action {
60
+ display: none;
61
+ position: relative;
62
+ margin-right: -8px;
63
+ border-radius: 4px;
64
+ width: 32px;
65
+ height: 32px;
66
+ color: var(--vp-c-text-3);
67
+ transition: color 0.25s;
68
+ }
69
+
70
+ .VPSidebarGroup.collapsible .action {
71
+ display: block;
72
+ }
73
+
74
+ .title:hover .action {
75
+ color: var(--vp-c-text-2);
76
+ }
77
+
78
+ .icon {
79
+ position: absolute;
80
+ top: 8px;
81
+ left: 8px;
82
+ width: 16px;
83
+ height: 16px;
84
+ fill: currentColor;
85
+ }
86
+
87
+ .icon.minus { opacity: 1; }
88
+ .icon.plus { opacity: 0; }
89
+
90
+ .VPSidebarGroup.collapsed .icon.minus { opacity: 0; }
91
+ .VPSidebarGroup.collapsed .icon.plus { opacity: 1; }
92
+
93
+ .items {
94
+ overflow: hidden;
95
+ }
96
+
97
+ .VPSidebarGroup.collapsed .items {
98
+ margin-bottom: -22px;
99
+ max-height: 0;
100
+ }
101
+
102
+ @media (min-width: 960px) {
103
+ .VPSidebarGroup.collapsed .items {
104
+ margin-bottom: -14px;
105
+ }
43
106
  }
44
107
  </style>