Last active
April 21, 2018 04:41
-
-
Save andreasvirkus/3373c2e5058445f83dc06df5b9c5bcfb to your computer and use it in GitHub Desktop.
Dropdown in Vue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="dropdown-wrapper" :class="{ open }"> | |
<a class="dropdown-title" @click="toggle"> | |
<span class="title">{{ item.text }}</span> | |
<span class="arrow" :class="open ? 'down' : 'right'"></span> | |
</a> | |
<DropdownTransition> | |
<ul class="nav-dropdown" v-show="open"> | |
<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"> | |
<a :href="childSubItem.link">{{ childSubItem.text }}</a> | |
</li> | |
</ul> | |
<a v-else :href="subItem.link">{{ subItem.text }}</a> | |
</li> | |
</ul> | |
</DropdownTransition> | |
</div> | |
</template> | |
<script> | |
import DropdownTransition from './DropdownTransition.vue' | |
export default { | |
components: { DropdownTransition }, | |
data() { | |
return { | |
open: false | |
} | |
}, | |
props: { | |
item: { | |
required: true | |
} | |
}, | |
methods: { | |
toggle() { | |
this.open = !this.open | |
} | |
} | |
} | |
</script> | |
<style> | |
.nav-dropdown { | |
transition height .1s ease-out | |
} | |
/* And some demo styles */ | |
.dropdown-wrapper .dropdown-title { | |
display: block; | |
} | |
.dropdown-wrapper .dropdown-title:hover { | |
border-color: transparent; | |
} | |
.dropdown-wrapper .dropdown-title .arrow { | |
vertical-align: middle; | |
margin-top: -1px; | |
margin-left: 0.4rem; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item { | |
color: inherit; | |
line-height: 1.7rem; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item h4 { | |
margin: 0.45rem 0 0; | |
border-top: 1px solid #eee; | |
padding: 0.45rem 1.5rem 0 1.25rem; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper { | |
padding: 0; | |
list-style: none; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem { | |
font-size: 0.9em; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item 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; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item a:hover { | |
color: #3eaf7c; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active { | |
color: #3eaf7c; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after { | |
content: ""; | |
width: 0; | |
height: 0; | |
border-left: 5px solid #3eaf7c; | |
border-top: 3px solid transparent; | |
border-bottom: 3px solid transparent; | |
position: absolute; | |
top: calc(50% - 2px); | |
left: 9px; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4 { | |
margin-top: 0; | |
padding-top: 0; | |
border-top: 0; | |
} | |
@media (max-width: 719px) { | |
.dropdown-wrapper.open .dropdown-title { | |
margin-bottom: 0.5rem; | |
} | |
.dropdown-wrapper .nav-dropdown { | |
transition: height 0.1s ease-out; | |
overflow: hidden; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item h4 { | |
border-top: 0; | |
margin-top: 0; | |
padding-top: 0; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item h4, | |
.dropdown-wrapper .nav-dropdown .dropdown-item > a { | |
font-size: 15px; | |
height: 2rem; | |
line-height: 2rem; | |
} | |
.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem { | |
font-size: 14px; | |
padding-left: 1rem; | |
} | |
} | |
@media (min-width: 719px) { | |
.dropdown-wrapper { | |
height: 1.8rem; | |
} | |
.dropdown-wrapper:hover .nav-dropdown { | |
display: block !important; | |
} | |
.dropdown-wrapper .dropdown-title .arrow { | |
border-left: 4px solid transparent; | |
border-right: 4px solid transparent; | |
border-top: 6px solid #ccc; | |
border-bottom: 0; | |
} | |
.dropdown-wrapper .nav-dropdown { | |
display: none; | |
height: auto !important; | |
box-sizing: border-box; | |
max-height: calc(100vh - 2.7rem); | |
overflow-y: auto; | |
position: absolute; | |
top: 100%; | |
right: 0; | |
background-color: #fff; | |
padding: 0.6rem 0; | |
border: 1px solid #ddd; | |
border-bottom-color: #ccc; | |
text-align: left; | |
border-radius: 0.25rem; | |
white-space: nowrap; | |
margin: 0; | |
} | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<transition name="dropdown" | |
@enter="setHeight" | |
@after-enter="unsetHeight" | |
@before-leave="setHeight"> | |
<slot></slot> | |
</transition> | |
</template> | |
<script> | |
export default { | |
name: 'SidebarGroup', | |
methods: { | |
setHeight (items) { | |
// explicitly set height so that it can be transitioned | |
items.style.height = items.scrollHeight + 'px' | |
}, | |
unsetHeight (items) { | |
items.style.height = '' | |
} | |
} | |
} | |
</script> | |
<style> | |
.dropdown-enter, | |
.dropdown-leave-to { | |
height 0 !important | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment