Skip to content

feat: refine group (fix#287) #669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@vuepress/theme-default/components/Page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function find (page, items, offset) {
const res = []
items.forEach(item => {
if (item.type === 'group') {
res.push(...item.children || [])
res.push(...item.descendants || [])
} else {
res.push(item)
}
Expand Down
54 changes: 2 additions & 52 deletions packages/@vuepress/theme-default/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
v-if="item.type === 'group'"
:item="item"
:first="i === 0"
:open="i === openGroupIndex"
:collapsable="item.collapsable || item.collapsible"
@toggle="toggleGroup(i)"
/>
:collapsable="item.collapsable || item.collapsible"/>
<SidebarLink v-else :item="item"/>
</li>
</ul>
Expand All @@ -23,58 +20,11 @@
import SidebarGroup from './SidebarGroup.vue'
import SidebarLink from './SidebarLink.vue'
import NavLinks from './NavLinks.vue'
import { isActive } from '../util'

export default {
components: { SidebarGroup, SidebarLink, NavLinks },

props: ['items'],

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 Down
72 changes: 67 additions & 5 deletions packages/@vuepress/theme-default/components/SidebarGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<p
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')"
@click="handleClick"
>
<span>{{ item.title }}</span>
<span
Expand All @@ -23,21 +23,83 @@
v-if="open || !collapsable"
>
<li v-for="child in item.children">
<SidebarLink :item="child"/>
<SidebarGroup v-if="child.type === 'group'"
:item="child"
:collapsable="child.collapsable"/>
<SidebarLink v-else :item="child" :sidebarDepth="item.sidebarDepth"/>
</li>
</ul>
</DropdownTransition>
</div>
</template>

<script>
import Vue from 'vue'
import SidebarLink from './SidebarLink.vue'
import DropdownTransition from './DropdownTransition.vue'
import { isActive } from '../util'

const bus = new Vue()

export default {
name: 'SidebarGroup',
props: ['item', 'first', 'open', 'collapsable'],
components: { SidebarLink, DropdownTransition }

components: { SidebarLink, DropdownTransition },

props: [
'item',
'first',
'collapsable'
],

data () {
return {
open: this.item.isolated && this.item.initialIsolatedOpen || false
}
},

created () {
this.initBusEvent()
this.refreshOpen()
},

watch: {
'$route' () {
this.refreshOpen()
}
},

methods: {
initBusEvent () {
const onRequestClose = this.onRequestClose.bind(this)
bus.$on('requestClose', onRequestClose)
this.$on('hook:destroyed', () => {
bus.$off('requestClose', onRequestClose)
})
},
refreshOpen () {
const arr = this.item.descendants || []
if (arr.some(c => isActive(this.$route, c.path))) {
this.open = true
}
},
handleClick () {
this.open = !this.open
if (this.open && !this.item.isolated) {
bus.$emit('requestClose', { groupDepth: this.item.groupDepth, target: this })
}
},
onRequestClose ({ groupDepth, target }) {
if (
target.$parent === this.$parent &&
groupDepth === this.item.groupDepth &&
!this.item.isolated &&
target !== this
) {
this.open = false
}
}
}
}
</script>

Expand All @@ -48,7 +110,7 @@ export default {
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading
> .sidebar-heading
cursor auto
color inherit

Expand Down
23 changes: 18 additions & 5 deletions packages/@vuepress/theme-default/components/SidebarLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ 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 },
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,10 +22,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

let configDepth
if ($page.frontmatter.sidebarDepth != null) {
configDepth = $page.frontmatter.sidebarDepth
} else if (sidebarDepth != null) {
configDepth = sidebarDepth
} else {
configDepth = $site.themeConfig.sidebarDepth
}
const maxDepth = configDepth == null ? 1 : configDepth

const displayAllHeaders = !!$site.themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
Expand Down
26 changes: 15 additions & 11 deletions packages/@vuepress/theme-default/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,26 +207,30 @@ function ensureEndingSlash (path) {
: path + '/'
}

function resolveItem (item, pages, base, isNested) {
function resolveItem (item, pages, base, groupDepth = 1) {
if (typeof item === 'string') {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
return Object.assign(resolvePage(pages, item[0], base), {
title: item[1]
})
} else {
if (isNested) {
console.error(
'[vuepress] Nested sidebar groups are not supported. ' +
'Consider using navbar + categories instead.'
)
}
const children = item.children || []
} else if (Array.isArray(item.children)) {
const descendants = []
const children = item.children.map(child => {
const resolvedItem = resolveItem(child, pages, base, groupDepth + 1)
;[].push.apply(descendants, resolvedItem.descendants || [resolvedItem])
return resolvedItem
})
return {
type: 'group',
title: item.title,
children: children.map(child => resolveItem(child, pages, base, true)),
collapsable: item.collapsable !== false
children,
descendants,
collapsable: item.collapsable !== false,
isolated: item.isolated === true,
initialIsolatedOpen: item.initialIsolatedOpen === true,
sidebarDepth: item.sidebarDepth,
groupDepth
}
}
}
8 changes: 7 additions & 1 deletion packages/docs/docs/theme/default-theme-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ module.exports = {

Sidebar groups are collapsable by default. You can force a group to be always open with `collapsable: false`.

When a group is open, other groups at the same level will be automatically closed. You can isolate a group's open status with `isolated: true`. And then you can config its initial open status with `initialIsolatedOpen: true`.

You can config a group's sidebarDepth with `sidebarDepth: 2`.

You can nest sidebar groups.

### Multiple Sidebars

If you wish to display different sidebars for different sections of content, first organize your pages into directories for each desired section:
Expand Down Expand Up @@ -329,7 +335,7 @@ module.exports = {
```

::: warning Note
Unlike the [built-in search](#built-in-search) engine which works out of the box, [Algolia DocSearch](https://community.algolia.com/docsearch/) requires you to submit your site to them for indexing before it starts working.
Unlike the [built-in search](#built-in-search) engine which works out of the box, [Algolia DocSearch](https://community.algolia.com/docsearch/) requires you to submit your site to them for indexing before it starts working.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is probably not relevant for this PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I have config my IDE to trim trailing whitespace. Should I add the whitespace back?

:::

For more options, refer to [Algolia DocSearch's documentation](https://github.com/algolia/docsearch#docsearch-options).
Expand Down
6 changes: 6 additions & 0 deletions packages/docs/docs/zh/theme/default-theme-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ module.exports = {

侧边栏的每个子组默认是可折叠的,你可以设置 `collapsable: false` 来让一个组永远都是展开状态。

当一个子组被展开时,跟它同级的其他子组会被折叠。你可以设置 `isolated: true` 来隔离一个组的展开状态。然后你可以设置 `initialIsolatedOpen: true` 来让一个被隔离的组在一开始就处于展开状态。

你可以通过 `sidebarDepth: 2` 来设置一个组的 sidebarDepth。

你可以嵌套组。

### 多个侧边栏

如果你想为不同的页面组来显示不同的侧边栏,首先,将你的页面文件组织成下述的目录结构:
Expand Down