Skip to content

Commit

Permalink
feat: dropdown Items in Navbar (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
ulivz authored and yyx990803 committed Apr 16, 2018
1 parent 37ea038 commit 79f8f14
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 35 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ https://vuepress.vuejs.org/

VuePress is still a work in progress. There are a few things that it currently does not support but are planned:

- Dropdown Items in Navbar
- Multi-Language Support
- Algolia DocSearch Integration
- Blogging support
Expand Down
18 changes: 18 additions & 0 deletions docs/default-theme-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ module.exports = {
}
```

These links can also be dropdown menus if you provide nested items via `items`:

```js
module.exports = {
themeConfig: {
nav: [
{
text: 'Languages',
items: [
{ text: 'Chinese', link: '/language/chinese' },
{ text: 'Japanese', link: '/language/japanese' }
]
}
]
}
}
```

## Sidebar

To enable the sidebar, use `themeConfig.sidebar`. The basic configuration expects an Array of links:
Expand Down
1 change: 0 additions & 1 deletion docs/guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ Each markdown file is compiled into HTML with [markdown-it](https://github.com/m

VuePress is still a work in progress. There are a few things that it currently does not support but are planned:

- Dropdown Items in Navbar
- Multi-Language Support
- Algolia DocSearch Integration
- Blogging support
Expand Down
152 changes: 152 additions & 0 deletions lib/default-theme/DropdownLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<template>
<div class="dropdown-wrapper" :class="{ open }">
<div class="dropdown-title" @click="toggle">
<span class="title">{{ item.text }}</span>
<span class="arrow"></span>
</div>
<ul class="nav-dropdown">
<li
class="dropdown-item"
v-for="subItem in item.items"
:key="subItem.link">
<h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
<ul class="dropdown-subitem-wrapper" v-if="subItem.type === 'links'">
<li
class="dropdown-subitem"
v-for="childSubItem in subItem.items"
:key="childSubItem.link">
<nav-link :item="childSubItem"></nav-link>
</li>
</ul>
<nav-link v-else :item="subItem"></nav-link>
</li>
</ul>
</div>
</template>

<script>
import { isExternal, ensureExt } from './util'
import NavLink from './NavLink.vue'
export default {
components: { NavLink },
data() {
return {
open: false
}
},
props: {
item: {
required: true
}
},
methods: {
toggle() {
this.open = !this.open
}
}
}
</script>

<style lang="stylus">
@import './styles/config.styl'
.dropdown-wrapper
.dropdown-title
.arrow
display inline-block
vertical-align middle
margin-top -1px
margin-left 6px
width 0
height 0
border-left 4px solid transparent
border-right 4px solid transparent
border-top 5px solid #ccc
.nav-dropdown
.dropdown-item
color inherit
line-height 1.7rem
h4
margin 0.45rem 0 0
border-top 1px solid #eee
padding 0.45rem 1.5rem 0 1.25rem
.dropdown-subitem-wrapper
padding 0
list-style none
.dropdown-subitem
font-size 0.9em
a
display block
height 1.7rem
line-height 1.7rem
position relative
border-bottom none
font-weight 400
margin-bottom 0
padding 0 1.5rem 0 1.25rem
&:hover
color $accentColor
&.router-link-active
color $accentColor
&::after
content ""
width 0
height 0
border-left 5px solid $accentColor
border-top 4px solid transparent
border-bottom 4px solid transparent
position absolute
top calc(50% - 3px)
left 10px
&:first-child h4
margin-top 0
padding-top 0
border-top 0
@media (max-width: $MQMobile)
.dropdown-wrapper
&.open .dropdown-title
margin-bottom 0.5rem
&:not(.open)
.dropdown-title .arrow
border-top 4px solid transparent
border-bottom 4px solid transparent
border-left 5px solid #ccc
.nav-dropdown
display none
.nav-dropdown
.dropdown-item
h4
border-top 0
margin-top 0
padding-top 0
h4, & > a
font-size 15px
height 2rem
line-height 2rem
.dropdown-subitem
font-size 14px
padding-left 1rem
@media (min-width: $MQMobile)
.dropdown-wrapper
&:hover .nav-dropdown
display block
.nav-dropdown
display none
box-sizing border-box;
max-height calc(100vh - 2.7rem)
overflow-y auto
position absolute
top 100%
right 0
background-color #fff
padding 10px 0
border 1px solid #ddd
border-bottom-color #ccc
text-align left
border-radius 0.25rem
white-space nowrap
margin 0
</style>
34 changes: 34 additions & 0 deletions lib/default-theme/NavLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<router-link
class="nav-link"
:to="link"
v-if="!isExternal(link)"
:exact="link === '/'"
>{{ item.text }}</router-link>
<a
v-else
:href="link"
target="_blank"
class="nav-link"
rel="noopener noreferrer"
>{{ item.text }}</a>
</template>

<script>
import { isExternal, ensureExt } from './util'
export default {
props: {
item: {
required: true
}
},
computed: {
link() {
return ensureExt(this.item.link)
}
},
methods: {
isExternal
}
}
</script>
67 changes: 36 additions & 31 deletions lib/default-theme/NavLinks.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
<template>
<nav class="nav-links" v-if="userLinks.length || githubLink">
<!-- user links -->
<template v-for="item in userLinks">
<a v-if="item.isOutbound"
:href="item.link"
target="_blank"
rel="noopener noreferrer">
{{ item.text }}
</a>
<router-link
v-else
:to="item.link"
:key="item.link"
:exact="item.link === '/'">
{{ item.text }}
</router-link>
</template>
<div
class="nav-item"
v-for="item in userLinks"
:key="item.link">
<dropdown-link
v-if="item.type === 'links'"
:item="item"></dropdown-link>
<nav-link v-else :item="item"></nav-link>
</div>
<!-- github link -->
<a v-if="githubLink"
:href="githubLink"
Expand All @@ -30,16 +24,18 @@

<script>
import OutboundLink from './OutboundLink.vue'
import { isActive, ensureExt, outboundRE } from './util'
import { isActive, resolveNavLinkItem } from './util'
import NavLink from './NavLink.vue'
import DropdownLink from './DropdownLink.vue'
export default {
components: { OutboundLink },
components: { OutboundLink, NavLink, DropdownLink },
computed: {
userLinks () {
return (this.$site.themeConfig.nav || []).map(item => ({
text: item.text,
link: ensureExt(item.link),
isOutbound: outboundRE.test(item.link)
return (this.$site.themeConfig.nav || []).map((link => {
return Object.assign(resolveNavLinkItem(link), {
items: (link.items || []).map(resolveNavLinkItem)
})
}))
},
githubLink () {
Expand All @@ -63,21 +59,30 @@ export default {
.nav-links
display inline-block
a
color inherit
font-weight 500
line-height 1.25rem
margin-left 1.5rem
color inherit
&:hover, &.router-link-active
color $accentColor
.nav-item
cursor: pointer
position relative
display inline-block
margin-left 1.5rem
font-weight 500
line-height 2rem
.github-link
margin-left 1.5rem
@media (max-width: $MQMobile)
.nav-links a
margin-left 0
.nav-links
.nav-item, .github-link
margin-left 0
@media (min-width: $MQMobile)
.nav-links a
&:hover, &.router-link-active
color $textColor
margin-bottom -2px
border-bottom 2px solid lighten($accentColor, 5%)
.nav-links
a
&:hover, &.router-link-active
color $textColor
margin-bottom -2px
border-bottom 2px solid lighten($accentColor, 5%)
</style>
3 changes: 2 additions & 1 deletion lib/default-theme/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ function resolveOpenGroupIndex (route, items) {
display none
border-bottom 1px solid $borderColor
padding 0.5rem 0 0.75rem 0
a
.nav-item, .github-link
display block
line-height 1.25rem
font-weight 600
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
Expand Down
12 changes: 11 additions & 1 deletion lib/default-theme/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ export function getHash (path) {
}
}

export function isExternal (path) {
return outboundRE.test(path)
}

export function ensureExt (path) {
if (outboundRE.test(path)) {
if (isExternal(path)) {
return path
}
const hashMatch = path.match(hashRE)
Expand Down Expand Up @@ -147,6 +151,12 @@ export function groupHeaders (headers) {
return headers.filter(h => h.level === 2)
}

export function resolveNavLinkItem (linkItem) {
return Object.assign(linkItem, {
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
})
}

function resolveMatchingSidebarConfig (route, sidebarConfig) {
if (Array.isArray(sidebarConfig)) {
return {
Expand Down

0 comments on commit 79f8f14

Please sign in to comment.