optimize navbar interaction
diff --git a/components/partials/Navbar.vue b/components/partials/Navbar.vue
index 871f486..48e662b 100644
--- a/components/partials/Navbar.vue
+++ b/components/partials/Navbar.vue
@@ -3,11 +3,10 @@
</template>
<script lang="ts">
-import Vue from 'vue';
import zhNav from './Navbar/zh';
import enNav from './Navbar/zh';
-export default Vue.extend({
+export default {
components: {
},
@@ -18,6 +17,6 @@
: enNav;
}
}
-});
+};
</script>
diff --git a/components/partials/Sidebar.vue b/components/partials/Sidebar.vue
index a2ec88b..9bd6cc9 100644
--- a/components/partials/Sidebar.vue
+++ b/components/partials/Sidebar.vue
@@ -7,7 +7,7 @@
:key="level0Post.dir"
>
<a class="bd-toc-link"
- :href="level0Post.children ? 'javascript:;' : rootPath + level0Post.dir"
+ :href="level0Post.children ? 'javascript:;' : level0Post.dir"
v-if="!level0Post.draft"
>
{{ level0Post.title }}
@@ -15,54 +15,14 @@
<ul class="nav bd-sidenav level1"
v-if="!level0Post.draft && level0Post.children"
>
- <li class="nav-item"
+ <SidebarNavItem
v-for="level1Post in level0Post.children"
:key="level1Post.dir"
+ :item="level1Post"
+ :parentPath="level0Post.dir"
+ :level="1"
>
- <a :href="level1Post.children ? 'javascript:;' : rootPath + level0Post.dir + '_' + level1Post.dir"
- v-if="!level1Post.draft"
- class="nav-link">{{ level1Post.title }}</a>
- <ul class="nav bd-sidenav level2"
- v-if="!level1Post.draft && level1Post.children"
- >
- <li class="nav-item"
- v-for="level2Post in level1Post.children"
- :key="level2Post.dir"
- >
- <div v-if="!level2Post.draft">
- <a class="nav-link"
- v-if="!level2Post.children"
- :href="rootPath + level0Post.dir + '_' + level1Post.dir + '_' + level2Post.dir"
- >
- {{ level2Post.title }}
- </a>
- <a class="nav-link"
- v-if="level2Post.children"
- @click="toggleChildren($event)"
- >
- {{ level2Post.title }}
- <span class="glyphicon glyphicon-menu-down"></span>
- <span class="glyphicon glyphicon-menu-up"></span>
- </a>
- <ul class="nav bd-sidenav level3"
- v-if="!level2Post.draft && level2Post.children"
- >
- <li class="nav-item"
- v-for="level3Post in level2Post.children"
- :key="level3Post.dir"
- >
- <a class="nav-link"
- :href="rootPath + level0Post.dir + '_' + level1Post.dir + '_' + level2Post.dir + '_' + level3Post.dir"
- v-if="!level3Post.draft"
- >
- {{ level3Post.title }}
- </a>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </li>
+ </SidebarNavItem>
</ul>
</div>
</div>
@@ -70,41 +30,48 @@
</template>
<script lang="ts">
-import Vue from 'vue';
-export default Vue.extend({
- computed: {
- rootPath(): string {
- return this.$store.state.config.rootPath + '/' + this.$store.state.locale + '/';
- }
+import SidebarNavItem from './SidebarNavItem';
+import scrollIntoView from 'scroll-into-view';
+
+export default {
+
+ components: {
+ SidebarNavItem
},
- methods: {
- toggleChildren(event: MouseEvent) {
- let el = event.target as any;
- while (el.nodeName !== 'LI' && el.parentNode) {
- el = el.parentNode;
+
+ mounted() {
+
+ setTimeout(() => {
+ const $actived = this.$el.querySelector('.actived');
+ if ($actived) {
+ scrollIntoView($actived, {
+ time: 200,
+ align: {
+ top: 0,
+ topOffset: 300
+ },
+ isScrollable: function(target, defaultIsScrollable){
+ return target.className && target.className.indexOf('bd-sidebar') >= 0;
+ }
+
+ });
}
- if (el === document) {
- return;
- }
- if (!el.className) {
- el.className = ' active';
- }
- else if (el.className.indexOf(' active') > -1) {
- el.className = el.className.replace(' active', '');
- }
- else {
- el.className += ' active';
- }
- }
+ }, 0);
}
-});
+};
</script>
<style lang="scss">
.bd-sidebar {
padding: 20px;
+ position: sticky;
+ z-index: 1000;
+ top: 0;
+ height: calc(100vh - 50px);
+ overflow-y: auto;
+ border-right: 1px solid #eee;
}
.bd-toc-item {
@@ -135,6 +102,8 @@
}
.page-content {
+ padding-bottom: 0;
+
.nav {
display: block;
}
@@ -154,26 +123,6 @@
top: -2px;
}
- .glyphicon {
- padding: 5px;
- color: #ccc;
- cursor: pointer;
- transform: scale(0.8);
- top: 2px;
- left: -5px;
- }
-
- .nav-link .glyphicon-menu-up {
- display: none;
- }
-
- .active .nav-link .glyphicon-menu-up {
- display: inline-block;
- }
-
- .active .nav-link .glyphicon-menu-down {
- display: none;
- }
.level1 {
.nav-link {
@@ -186,26 +135,21 @@
}
}
- .level2, .level3 {
+ .level1, .level2 {
margin-top: 0;
}
- .level2 .nav-link {
- color: #666;
+ .level1 .nav-link {
+ color: #444;
}
- .nav.level3 {
+ .nav.level2 {
border-left: 1px solid #eee;
padding-left: 10px;
margin-left: 0;
- display: none;
}
- .level2 .active .level3 {
- display: block;
- }
-
- .level3 .nav-link {
+ .level2 .nav-link {
margin: 2px 0;
color: #888;
}
diff --git a/components/partials/SidebarNavItem.vue b/components/partials/SidebarNavItem.vue
new file mode 100644
index 0000000..27fc3fc
--- /dev/null
+++ b/components/partials/SidebarNavItem.vue
@@ -0,0 +1,94 @@
+<template>
+<li
+ :class="['nav-item', isActived ? 'actived' : '']"
+ v-if="!item.draft"
+>
+ <a class="nav-link"
+ v-if="!item.children"
+ :href="link"
+ >
+ {{ item.title }}
+ </a>
+
+ <a
+ class="nav-link"
+ v-else
+ @click="toggleCollapsed"
+ >
+ {{ item.title }}
+ <span :class="['glyphicon', collapsed ? 'glyphicon-menu-down' : 'glyphicon-menu-up']"></span>
+ </a>
+
+ <ul :class="['nav', 'bd-sidenav', 'level' + level]"
+ v-if="!item.draft && item.children && !collapsed"
+ >
+ <SidebarNavItem
+ v-for="child in item.children"
+ :parentPath="path"
+ :item="child"
+ :level="level + 1"
+ ></SidebarNavItem>
+ </ul>
+</li>
+</template>
+
+
+<script lang="ts">
+export default {
+
+ name: 'SidebarNavItem',
+
+ props: ['item', 'parentPath', 'level'],
+
+ computed: {
+ link() {
+ return this.$store.state.config.rootPath + '/' + this.$store.state.locale
+ + '/' + this.path;
+ },
+
+ isActived() {
+ return this.$route.params.post === this.path;
+ }
+ },
+
+ data() {
+ const path = this.parentPath + '_' + this.item.dir;
+ const isSelfOrChildActived = this.$route.params.post.startsWith(path);
+ return {
+ get path() {
+ return path;
+ },
+ collapsed: this.level >= 2 && !isSelfOrChildActived
+ }
+ },
+
+ methods: {
+ toggleCollapsed() {
+ this.collapsed = !this.collapsed
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+.page-content {
+ .nav-item {
+ cursor: pointer;
+
+ &.actived {
+ .nav-link {
+ color: #5470c6
+ }
+ }
+
+ .glyphicon {
+ padding: 5px;
+ color: #ccc;
+ cursor: pointer;
+ transform: scale(0.8);
+ top: 2px;
+ left: -5px;
+ }
+ }
+}
+</style>
diff --git a/layouts/default.vue b/layouts/default.vue
index dae60be..c8abfde 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -3,7 +3,7 @@
<navbar />
<div class="page-main">
- <div class="page-content single-page">
+ <div class="page-content single-page container-fluid row flex-xl-nowrap">
<sidebar />
<div class="bd-content col-sm-7 pl-sm-2 col-12">
diff --git a/package-lock.json b/package-lock.json
index 1fb7f3d..3dcafe2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8004,8 +8004,8 @@
}
},
"markdown-it-toc-done-right": {
- "version": "git+ssh://git@github.com/Ovilia/markdown-it-toc-done-right.git#15afef001701efb604604dd1dcaa22a2fd753f34",
- "from": "git+ssh://git@github.com/Ovilia/markdown-it-toc-done-right.git"
+ "version": "git+https://github.com/Ovilia/markdown-it-toc-done-right.git#0b920e5fcd46a080309569f8c9b5fce91864bf0d",
+ "from": "git+https://github.com/Ovilia/markdown-it-toc-done-right.git"
},
"md5.js": {
"version": "1.3.5",
@@ -10935,6 +10935,11 @@
"ajv-keywords": "^3.4.1"
}
},
+ "scroll-into-view": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/scroll-into-view/-/scroll-into-view-1.15.0.tgz",
+ "integrity": "sha512-Ytbg8O1GlN8vOOZMPDOrjXixAFXZ4oJklxHkYREqdUFYo+a8qVuPX16U3nRkifKnM8kkvY9sOy7EL30HaeW07Q=="
+ },
"scss-tokenizer": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
diff --git a/package.json b/package.json
index 69d61e2..f3c0cba 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,8 @@
"markdown-it-highlightjs": "^3.1.0",
"markdown-it-toc-done-right": "git+https://github.com/Ovilia/markdown-it-toc-done-right.git",
"nuxt": "^2.0.0",
- "nuxt-i18n": "^6.7.2"
+ "nuxt-i18n": "^6.7.2",
+ "scroll-into-view": "^1.15.0"
},
"devDependencies": {
"@nuxt/typescript-build": "^0.6.0",
diff --git a/pages/en/_post.vue b/pages/en/_post.vue
index cbcc8dc..37faf39 100644
--- a/pages/en/_post.vue
+++ b/pages/en/_post.vue
@@ -3,16 +3,15 @@
</template>
<script lang="ts">
-import Vue from 'vue';
import {getPostData} from '../helper/post';
-export default Vue.extend({
+export default {
components: {
},
async asyncData({params}) {
return await getPostData(params.post, 'en');
}
-});
+};
</script>