Skip to content
This repository was archived by the owner on Mar 7, 2025. It is now read-only.

Commit cec2af2

Browse files
saltysugaregoist
authored andcommitted
feat: update sidebar ui (#257)
* update sidebar ui * fix dark theme * Update docs * Update style * Refactor * Remove unused style * Update style
1 parent 94b8168 commit cec2af2

File tree

11 files changed

+236
-128
lines changed

11 files changed

+236
-128
lines changed

src/components/PageToc.vue

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<template>
2+
<div
3+
class="PageToc"
4+
v-if="
5+
!$store.state.fetchingFile &&
6+
link.toc !== false &&
7+
link.link === $route.path &&
8+
$store.state.page.headings &&
9+
$store.state.page.headings.length > 0
10+
"
11+
>
12+
<router-link
13+
class="PageTocHeading"
14+
:to="{hash: heading.slug}"
15+
:data-level="heading.level"
16+
v-for="heading in $store.state.page.headings"
17+
:key="heading.slug"
18+
v-html="heading.text"
19+
></router-link>
20+
</div>
21+
</template>
22+
23+
<script>
24+
export default {
25+
props: {
26+
link: {
27+
type: Object,
28+
required: true
29+
}
30+
}
31+
}
32+
</script>
33+
34+
<style scoped>
35+
.PageToc {
36+
border-left: 1px solid var(--border-color);
37+
margin-left: 16px;
38+
margin-top: 10px;
39+
}
40+
41+
.PageTocHeading {
42+
display: flex;
43+
line-height: 1;
44+
position: relative;
45+
46+
&:not(:last-child) {
47+
margin-bottom: 8px;
48+
}
49+
50+
&[data-level='2'] {
51+
margin-left: 16px;
52+
}
53+
54+
&.router-link-exact-active {
55+
font-weight: bold;
56+
color: var(--sidebar-link-active-color);
57+
}
58+
}
59+
</style>

src/components/Sidebar.vue

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
v-for="(item, index) in $store.getters.sidebar"
1515
:key="index"
1616
:item="item"
17-
:open="currentOpenIndex === index"
18-
@toggle="openSidebar(index)"
17+
:open="openItems.indexOf(index) !== -1"
18+
@toggle="toggleItem(index)"
1919
/>
2020
</div>
2121

@@ -35,23 +35,33 @@ export default {
3535
},
3636
data() {
3737
return {
38-
currentOpenIndex: 0
38+
openItems: []
3939
}
4040
},
4141
watch: {
4242
'$route.path': {
4343
handler() {
44-
this.currentOpenIndex = this.getCurrentIndex(
44+
const index = this.getCurrentIndex(
4545
this.$route.path,
4646
this.$store.getters.sidebar
4747
)
48+
this.openItem(index)
4849
},
4950
immediate: true
5051
}
5152
},
5253
methods: {
53-
openSidebar(index) {
54-
this.currentOpenIndex = this.currentOpenIndex === index ? -1 : index
54+
openItem(index) {
55+
if (this.openItems.indexOf(index) === -1) {
56+
this.openItems.push(index)
57+
}
58+
},
59+
toggleItem(index) {
60+
if (this.openItems.indexOf(index) === -1) {
61+
this.openItems.push(index)
62+
} else {
63+
this.openItems = this.openItems.filter(v => v !== index)
64+
}
5565
},
5666
getCurrentIndex(currentPath, sidebarItems) {
5767
for (let idx = 0; idx < sidebarItems.length; idx++) {
@@ -63,7 +73,7 @@ export default {
6373
return idx
6474
}
6575
}
66-
return -1
76+
return 0
6777
},
6878
getChildren(item) {
6979
return item.children || item.links || []

src/components/SidebarItem.vue

Lines changed: 101 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,66 @@
22
<div :class="['SidebarItem', item.title && 'hasTitle']">
33
<div
44
class="ItemTitle"
5-
v-if="item.title"
6-
:collapsable="item.collapsable"
7-
:class="{collapsable: item.collapsable}"
5+
:class="{collapsable: item.collapsable !== false}"
6+
v-if="item.title && children"
87
@click="$emit('toggle')"
98
>
10-
{{ item.title }}
11-
<span
12-
v-if="item.collapsable"
13-
class="arrow"
14-
:class="open ? 'down' : 'right'"
15-
></span>
9+
<span v-if="item.collapsable !== false" class="arrow" :class="{open}">
10+
<svg
11+
width="6"
12+
height="10"
13+
viewBox="0 0 6 10"
14+
fill="none"
15+
xmlns="http://www.w3.org/2000/svg"
16+
>
17+
<path
18+
d="M1.4 8.56L4.67 5M1.4 1.23L4.66 4.7"
19+
stroke="currentColor"
20+
stroke-linecap="square"
21+
/>
22+
</svg>
23+
</span>
24+
<span>{{ item.title }}</span>
25+
</div>
26+
<uni-link
27+
class="ItemLink"
28+
:class="{active: $route.path === item.link}"
29+
v-if="item.title && item.link"
30+
:to="item.link"
31+
>{{ item.title }}</uni-link
32+
>
33+
<div class="ItemLinkToc" v-if="item.title && item.link">
34+
<PageToc :link="item" />
1635
</div>
17-
<template v-if="!item.collapsable || open">
18-
<template v-for="(link, index) of children">
36+
37+
<div
38+
class="ItemChildren"
39+
v-if="children && (open || item.collapsable === false)"
40+
>
41+
<div class="ItemChild" v-for="(link, index) of children" :key="index">
1942
<uni-link
20-
class="ItemLink"
21-
:key="index"
43+
class="ItemChildLink"
44+
:class="{active: $route.path === link.link}"
2245
:to="link.link"
2346
:openInNewTab="link.openInNewTab"
2447
:prefetchFiles="getPrefetchFiles(link.link)"
2548
>{{ link.title }}</uni-link
2649
>
27-
<div
28-
class="LinkToc"
29-
v-if="
30-
!$store.state.fetchingFile &&
31-
link.toc !== false &&
32-
link.link === $route.path &&
33-
$store.state.page.headings &&
34-
$store.state.page.headings.length > 0
35-
"
36-
:key="`toc-${index}`"
37-
>
38-
<router-link
39-
class="TocHeading"
40-
:to="{hash: heading.slug}"
41-
:data-level="heading.level"
42-
v-for="heading in $store.state.page.headings"
43-
:key="heading.slug"
44-
v-html="heading.text"
45-
></router-link>
46-
</div>
47-
</template>
48-
</template>
50+
<PageToc :link="link" />
51+
</div>
52+
</div>
4953
</div>
5054
</template>
5155

5256
<script>
5357
import {isExternalLink, getFileUrl, getFilenameByPath} from '../utils'
5458
import UniLink from './UniLink.vue'
59+
import PageToc from './PageToc.vue'
5560
5661
export default {
5762
components: {
58-
UniLink
63+
UniLink,
64+
PageToc
5965
},
6066
props: {
6167
item: {
@@ -75,7 +81,7 @@ export default {
7581
},
7682
computed: {
7783
children() {
78-
return this.item.children || this.item.links || []
84+
return this.item.children || this.item.links
7985
}
8086
},
8187
methods: {
@@ -105,66 +111,81 @@ export default {
105111
<style scoped>
106112
.SidebarItem {
107113
&:not(:last-child) {
108-
margin-bottom: 1.2rem;
114+
margin-bottom: 10px;
109115
}
110116
111-
&.hasTitle {
112-
& .ItemLink {
113-
font-size: 0.9rem;
114-
}
115-
}
117+
font-size: 0.875rem;
116118
117-
&.hasTitle >>> .TocHeading {
118-
font-size: 0.9rem;
119+
& a {
120+
color: var(--sidebar-link-color);
121+
122+
&:hover {
123+
color: var(--sidebar-link-active-color);
124+
}
119125
}
120126
}
121127
122128
.ItemTitle {
123-
font-size: 1rem;
124129
padding: 0 20px;
125130
margin-bottom: 10px;
126131
position: relative;
127-
color: var(--sidebar-section-title-color);
128-
text-transform: uppercase;
132+
color: var(--sidebar-link-color);
133+
user-select: none;
134+
font-size: 0;
129135
130-
&.collapsable {
131-
&:hover {
132-
cursor: pointer;
133-
}
136+
&.collapsable:hover {
137+
cursor: pointer;
138+
color: var(--sidebar-link-active-color);
139+
}
140+
141+
& span {
142+
font-size: 0.9rem;
134143
}
135144
}
136145
137146
.ItemLink {
138-
padding: 2px 20px;
147+
margin: 0 20px;
139148
display: flex;
140-
font-size: 1.1rem;
141-
position: relative;
149+
align-items: center;
150+
151+
&:before {
152+
content: '';
153+
display: block;
154+
width: 4px;
155+
height: 4px;
156+
border-radius: 50%;
157+
background-color: var(--sidebar-link-arrow-color);
158+
margin-right: 8px;
159+
}
142160
143161
&.active {
162+
color: var(--sidebar-link-active-color);
144163
font-weight: bold;
145164
}
146165
}
147166
148-
.TocHeading {
149-
display: flex;
150-
line-height: 1.4;
151-
margin: 5px 0;
152-
position: relative;
167+
.ItemLinkToc {
168+
margin: 0 8px;
169+
}
153170
154-
&[data-level='2'] {
155-
padding: 0 20px;
156-
&:before {
157-
content: '-';
158-
margin-right: 5px;
159-
color: #979797;
160-
}
161-
}
171+
.ItemChildren {
172+
border-left: 1px solid var(--border-color);
173+
margin: 0 20px;
174+
}
162175
163-
&[data-level='3'] {
164-
padding: 0 20px 0 40px;
176+
.ItemChild {
177+
&:not(:last-child) {
178+
margin-bottom: 10px;
165179
}
180+
}
181+
182+
.ItemChildLink {
183+
padding-left: 16px;
184+
display: flex;
185+
position: relative;
186+
line-height: 1;
166187
167-
&.router-link-exact-active {
188+
&.active {
168189
font-weight: bold;
169190
}
170191
}
@@ -175,20 +196,18 @@ a {
175196
}
176197
177198
.arrow {
199+
width: 16px;
178200
display: inline-block;
179-
position: relative;
180-
top: -0.1em;
181-
left: 0.5em;
182-
&.right {
183-
border-left: 6px solid #ccc;
184-
border-top: 4px solid transparent;
185-
border-bottom: 4px solid transparent;
201+
color: var(--sidebar-link-arrow-color);
202+
203+
& svg {
204+
transition: all 0.15s ease;
186205
}
187206
188-
&.down {
189-
border-top: 6px solid #ccc;
190-
border-left: 4px solid transparent;
191-
border-right: 4px solid transparent;
207+
&.open {
208+
& svg {
209+
transform: rotate(90deg);
210+
}
192211
}
193212
}
194213
</style>

src/css/main.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ body {
22
margin: 0;
33
color: var(--text-color);
44
background: var(--page-background);
5+
text-rendering: optimizeLegibility;
6+
-webkit-font-smoothing: antialiased;
57
font: 16px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
68
}
79

0 commit comments

Comments
 (0)