Skip to content

Commit

Permalink
feat($theme-default): refine sidebar groups (#1257)
Browse files Browse the repository at this point in the history
Close: #814 
Close: #783
Close: #287
  • Loading branch information
ulivz committed Feb 3, 2019
1 parent caca1db commit 01dd45b
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 107 deletions.
19 changes: 12 additions & 7 deletions packages/@vuepress/theme-default/components/Page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -177,20 +177,25 @@ function resolveNext (page, items) {
function find (page, items, offset) {
const res = []
items.forEach(item => {
if (item.type === 'group') {
res.push(...item.children || [])
} else {
res.push(item)
}
})
flattern(items, res)
for (let i = 0; i < res.length; i++) {
const cur = res[i]
if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
return res[i + offset]
}
}
}
function flattern (items, res) {
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].type === 'group') {
flattern(items[i].children || [], res)
} else {
res.push(items[i])
}
}
}
</script>

<style lang="stylus">
Expand Down
74 changes: 9 additions & 65 deletions packages/@vuepress/theme-default/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,21 @@
<aside class="sidebar">
<NavLinks/>
<slot name="top"/>
<ul class="sidebar-links" v-if="items.length">
<li v-for="(item, i) in items" :key="i">
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:first="i === 0"
:open="i === openGroupIndex"
:collapsable="item.collapsable || item.collapsible"
@toggle="toggleGroup(i)"
/>
<SidebarLink v-else :item="item"/>
</li>
</ul>
<SidebarLinks :depth="0" :items="items"/>
<slot name="bottom"/>
</aside>
</template>

<script>
import SidebarGroup from './SidebarGroup.vue'
import SidebarLink from './SidebarLink.vue'
import SidebarLinks from './SidebarLinks.vue'
import NavLinks from './NavLinks.vue'
import { isActive } from '../util'
export default {
components: { SidebarGroup, SidebarLink, NavLinks },
name: 'Sidebar',
props: ['items'],
components: { SidebarLinks, NavLinks },
data () {
return {
openGroupIndex: 0
}
},
created () {
this.refreshIndex()
},
watch: {
'$route' () {
this.refreshIndex()
}
},
methods: {
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex = index
}
},
toggleGroup (index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index
},
isActive (page) {
return isActive(this.$route, page.regularPath)
}
}
}
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) {
return i
}
}
return -1
props: ['items']
}
</script>

Expand All @@ -97,15 +39,17 @@ function resolveOpenGroupIndex (route, items) {
line-height 1.25rem
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
.sidebar-links
& > .sidebar-links
padding 1.5rem 0
& > li:not(:first-child)
margin-top .75rem
@media (max-width: $MQMobile)
.sidebar
.nav-links
display block
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
top calc(1rem - 2px)
.sidebar-links
& > .sidebar-links
padding 1rem 0
</style>
90 changes: 71 additions & 19 deletions packages/@vuepress/theme-default/components/SidebarGroup.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
<template>
<section
class="sidebar-group"
:class="{ first, collapsable }"
:class="[
{
collapsable,
'is-sub-group': depth !== 0
},
`depth-${depth}`
]"
>
<router-link
v-if="item.path"
class="sidebar-heading clickable"
:class="{
open,
'active': isActive($route, item.path)
}"
:to="item.path"
@click.native="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</router-link>

<p
v-else
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')"
Expand All @@ -17,40 +42,59 @@
</p>

<DropdownTransition>
<ul
ref="items"
<SidebarLinks
class="sidebar-group-items"
:items="item.children"
v-if="open || !collapsable"
>
<li v-for="child in item.children">
<SidebarLink :item="child"/>
</li>
</ul>
:sidebarDepth="item.sidebarDepth"
:depth="depth + 1"
/>
</DropdownTransition>
</section>
</template>

<script>
import SidebarLink from './SidebarLink.vue'
import { isActive } from '../util'
import DropdownTransition from './DropdownTransition.vue'
export default {
name: 'SidebarGroup',
props: ['item', 'first', 'open', 'collapsable'],
components: { SidebarLink, DropdownTransition }
props: ['item', 'open', 'collapsable', 'depth'],
components: { DropdownTransition },
// ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
beforeCreate () {
this.$options.components.SidebarLinks = require('./SidebarLinks.vue').default
},
methods: { isActive }
}
</script>

<style lang="stylus">
.sidebar-group
&:not(.first)
margin-top 1em
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading
.sidebar-heading:not(.clickable)
cursor auto
color inherit
// refine styles of nested sidebar groups
&.is-sub-group
padding-left 0
& > .sidebar-heading
font-size 0.95em
line-height 1.4
font-weight normal
padding-left 2rem
&:not(.clickable)
opacity 0.5
& > .sidebar-group-items
padding-left 1rem
& > li > .sidebar-link
font-size: 0.95em;
border-left none
&.depth-2
& > .sidebar-heading
border-left none
.sidebar-heading
color #999
Expand All @@ -59,19 +103,27 @@ export default {
font-size 1.1em
font-weight bold
// text-transform uppercase
padding 0 1.5rem
margin-top 0
margin-bottom 0.5rem
padding 0.35rem 1.5rem 0.35rem 1.25rem
width 100%
box-sizing border-box
margin 0
border-left 0.25rem solid transparent
&.open, &:hover
color inherit
.arrow
position relative
top -0.12em
left 0.5em
&:.open .arrow
top -0.18em
&.clickable
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
&:hover
color $accentColor
.sidebar-group-items
transition height .1s ease-out
font-size 0.95em
overflow hidden
</style>
32 changes: 26 additions & 6 deletions packages/@vuepress/theme-default/components/SidebarLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,22 @@ import { isActive, hashRE, groupHeaders } from '../util'
export default {
functional: true,
props: ['item'],
props: ['item', 'sidebarDepth'],
render (h, { parent: { $page, $site, $route }, props: { item }}) {
render (h,
{
parent: {
$page,
$site,
$route,
$themeConfig,
$themeLocaleConfig
},
props: {
item,
sidebarDepth
}
}) {
// use custom active class matching logic
// due to edge case of paths ending with / + hash
const selfActive = isActive($route, item.path)
Expand All @@ -16,11 +29,17 @@ export default {
? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
: selfActive
const link = renderLink(h, item.path, item.title || item.path, active)
const configDepth = $page.frontmatter.sidebarDepth != null
? $page.frontmatter.sidebarDepth
: $site.themeConfig.sidebarDepth
const configDepth = $page.frontmatter.sidebarDepth ||
sidebarDepth ||
$themeLocaleConfig.sidebarDepth ||
$themeConfig.sidebarDepth
const maxDepth = configDepth == null ? 1 : configDepth
const displayAllHeaders = !!$site.themeConfig.displayAllHeaders
const displayAllHeaders = $themeLocaleConfig.displayAllHeaders ||
$themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
} else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
Expand Down Expand Up @@ -64,6 +83,7 @@ function renderChildren (h, children, path, route, maxDepth, depth = 1) {
font-size 0.95em
a.sidebar-link
font-size 1em
font-weight 400
display inline-block
color $textColor
Expand Down
Loading

0 comments on commit 01dd45b

Please sign in to comment.