Skip to content

Commit d19fab4

Browse files
committed
feat: Add CDropdown and child components.
1 parent f9ff39a commit d19fab4

File tree

6 files changed

+204
-0
lines changed

6 files changed

+204
-0
lines changed

src/components/Dropdown/CDropdown.vue

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<template>
2+
<li :class="computedDropdownClasses">
3+
<a href="#"
4+
aria-haspopup="true"
5+
:aria-expanded="visible"
6+
:class="computedToggleClasses"
7+
@click="click($event)"
8+
ref="toggle"
9+
>
10+
<slot name="button">
11+
<button class="btn btn-outline-primary dropdown-toggle">{{text}}</button>
12+
</slot>
13+
</a>
14+
<div :class="computedMenuClasses" ref="menu" v-on-clickaway="hide">
15+
<slot></slot>
16+
</div>
17+
</li>
18+
</template>
19+
<script>
20+
import Popper from 'popper.js'
21+
import { mixin as clickaway } from 'vue-clickaway'
22+
23+
export default {
24+
name: 'CDropdown',
25+
mixins: [ clickaway ],
26+
data () {
27+
return {
28+
visible: this.show
29+
}
30+
},
31+
props: {
32+
text: {
33+
type: String,
34+
default: 'Dropdown'
35+
},
36+
show: Boolean,
37+
dropup: Boolean,
38+
disabled: Boolean,
39+
right: Boolean,
40+
menuClasses: String,
41+
toggleClasses: String,
42+
popperConfig: Object
43+
// popperConfig: {
44+
// type: Object,
45+
// default () {
46+
// return {
47+
// modifiers: {
48+
// placement: 'bottom-end',
49+
// offset: {
50+
// offset: '20px'
51+
// },
52+
// computeStyle: {
53+
// enabled: true
54+
// },
55+
// flip: {
56+
// enabled: true
57+
// }
58+
// }
59+
// }
60+
// }
61+
// }
62+
},
63+
mounted () {
64+
this.checkForPopper()
65+
},
66+
methods:{
67+
hide () {
68+
if(this.$refs.menu.classList.contains('show'))
69+
this.toggle(false)
70+
},
71+
click (e) {
72+
e.preventDefault()
73+
this.toggle(!this.visible)
74+
},
75+
toggle (visible) {
76+
if(this.disabled)
77+
return
78+
this.visible = visible
79+
this.checkForPopper()
80+
},
81+
checkForPopper () {
82+
if(this.popperConfig)
83+
setTimeout(() => this.visible ? this.createPopper() : this.removePopper(), 0)
84+
},
85+
removePopper () {
86+
if (this._popper) {
87+
this._popper.destroy()
88+
}
89+
this._popper = null
90+
},
91+
createPopper () {
92+
this.removePopper()
93+
this._popper = new Popper(this.$refs.toggle, this.$refs.menu, this.popperConfig)
94+
}
95+
},
96+
computed: {
97+
computedDropdownClasses () {
98+
return [
99+
'dropdown',
100+
{
101+
'dropup': this.dropup,
102+
'show': this.visible
103+
}
104+
]
105+
},
106+
computedToggleClasses () {
107+
return [
108+
this.toggleClasses,
109+
{
110+
'disabled' : this.disabled
111+
}
112+
]
113+
},
114+
computedMenuClasses () {
115+
return [
116+
this.menuClasses,
117+
'dropdown-menu',
118+
this.right ? 'dropdown-menu-right' : 'dropdown-menu-left',
119+
{ 'show': this.visible }
120+
]
121+
}
122+
},
123+
}
124+
</script>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { mergeData } from 'vue-functional-data-merge'
2+
3+
export const props = {
4+
tag: {
5+
type: String,
6+
default: 'div'
7+
}
8+
}
9+
10+
export default {
11+
functional: true,
12+
name: 'CDropdownDivider',
13+
props,
14+
render (h, { props, data }) {
15+
return h(
16+
props.tag,
17+
mergeData(data, {
18+
staticClass: 'dropdown-divider',
19+
attrs: { role: 'separator' }
20+
})
21+
)
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { mergeData } from 'vue-functional-data-merge'
2+
3+
export const props = {
4+
tag: {
5+
type: String,
6+
default: 'h6'
7+
}
8+
}
9+
10+
export default {
11+
functional: true,
12+
name: 'CDropdownHeader',
13+
props,
14+
render (h, { props, data, children }) {
15+
return h(
16+
props.tag,
17+
mergeData(data, {
18+
staticClass: 'dropdown-header',
19+
}),
20+
children
21+
)
22+
}
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { mergeData } from 'vue-functional-data-merge'
2+
import CLink, { propsFactory as linkPropsFactory } from '../Link/CLink'
3+
4+
export const props = linkPropsFactory()
5+
6+
export default {
7+
functional: true,
8+
name: 'CDropdownItem',
9+
props,
10+
render (h, { props, data, children }) {
11+
return h(
12+
CLink,
13+
mergeData(data, {
14+
props,
15+
staticClass: 'dropdown-item',
16+
attrs: { role: 'menuitem' }
17+
}),
18+
children
19+
)
20+
}
21+
}

src/components/Dropdown/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import CDropdown from './CDropdown'
2+
import CDropdownHeader from './CDropdownHeader'
3+
import CDropdownDivider from './CDropdownDivider'
4+
import CDropdownItem from './CDropdownItem'
5+
6+
7+
export {
8+
CDropdown,
9+
CDropdownHeader,
10+
CDropdownDivider,
11+
CDropdownItem
12+
}

src/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from './Progress'
1414
export * from './Alert'
1515
export * from './Button'
1616
export * from './Card'
17+
export * from './Dropdown'

0 commit comments

Comments
 (0)