Skip to content

Commit d194227

Browse files
committed
Feat: Render CDropdown on popper.js by default
1 parent e017168 commit d194227

File tree

2 files changed

+107
-44
lines changed

2 files changed

+107
-44
lines changed

src/components/Dropdown/CDropdown.vue

Lines changed: 105 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,8 @@
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>
191
<script>
2+
import CLink from '../Link/CLink'
203
import Popper from 'popper.js'
214
import { mixin as clickaway } from 'vue-clickaway'
5+
import { deepObjectsMerge } from '@coreui/coreui/dist/js/coreui-utilities'
226
237
export default {
248
name: 'CDropdown',
@@ -33,20 +17,34 @@ export default {
3317
this.createPopper
3418
},
3519
props: {
36-
text: {
20+
buttonContent: {
3721
type: String,
3822
default: 'Dropdown'
3923
},
4024
show: Boolean,
4125
dropup: Boolean,
4226
disabled: Boolean,
43-
right: Boolean,
44-
menuClasses: String,
45-
toggleClasses: String,
46-
popperConfig: Object
27+
addMenuClasses: String,
28+
addButtonClasses: String,
29+
nav: Boolean,
30+
noCaret: Boolean,
31+
variant: {
32+
type: String,
33+
default: 'secondary'
34+
},
35+
size: {
36+
type: String,
37+
validator: val => ['sm', 'lg'].includes(val)
38+
},
39+
split: Boolean,
40+
offset: Number,
41+
placement: String,
42+
noFlip: Boolean,
43+
popperConfig: Object,
44+
noPopper: Boolean,
4745
},
4846
mounted () {
49-
this.checkForPopper()
47+
this.menagePopper()
5048
},
5149
methods:{
5250
hide () {
@@ -57,14 +55,16 @@ export default {
5755
e.preventDefault()
5856
this.toggle(!this.visible)
5957
},
60-
toggle (visible) {
58+
toggle (value) {
6159
if(this.disabled)
6260
return
63-
this.visible = visible
64-
this.checkForPopper()
61+
setTimeout(() => {
62+
this.visible = value
63+
this.menagePopper()
64+
}, 0)
6565
},
66-
checkForPopper () {
67-
if(this.popperConfig)
66+
menagePopper () {
67+
if(!this.noPopper)
6868
setTimeout(() => this.visible ? this.createPopper() : this.removePopper(), 0)
6969
},
7070
removePopper () {
@@ -73,37 +73,102 @@ export default {
7373
}
7474
this._popper = null
7575
},
76-
createPopper (element) {
76+
createPopper () {
7777
this.removePopper()
78-
this._popper = new Popper(this.$refs.toggle, this.$refs.menu, this.popperConfig)
78+
this._popper = new Popper(this.$refs.toggle, this.$refs.menu, this.computedPopperConfig)
7979
}
8080
},
8181
computed: {
82+
generatedPopperConfig () {
83+
return {
84+
placement: this.placement ? this.placement : this.dropup ? 'top-start' : 'bottom-start',
85+
modifiers: {
86+
offset: { offset: this.offset || 0 },
87+
flip: { enabled: !this.noFlip }
88+
}
89+
}
90+
},
91+
computedPopperConfig () {
92+
return deepObjectsMerge(this.generatedPopperConfig, this.popperConfig || {})
93+
},
8294
computedDropdownClasses () {
8395
return [
84-
'dropdown',
96+
!this.dropup ? 'dropdown': 'dropup',
8597
{
86-
'dropup': this.dropup,
87-
'show': this.visible
98+
'show': this.visible,
99+
'nav-item': this.nav,
100+
'btn-group': this.haveButtonClasses
88101
}
89102
]
90103
},
91-
computedToggleClasses () {
104+
buttonTag () {
105+
return this.nav ? CLink : 'button'
106+
},
107+
haveButtonClasses () {
108+
return this.nav && !this.split ? Boolean(this.$options.propsData.variant) : true
109+
},
110+
computedButtonClasses () {
92111
return [
93-
this.toggleClasses,
112+
this.addButtonClasses,
113+
this.haveButtonClasses ? `btn btn-${this.variant}` : 'nav-link',
94114
{
95-
'disabled' : this.disabled
115+
'dropdown-toggle': !this.noCaret && !this.split,
116+
[`btn-${this.size}`]: this.size,
117+
'disabled' : this.disabled,
96118
}
97119
]
98120
},
99121
computedMenuClasses () {
100122
return [
101-
this.menuClasses,
123+
this.addMenuClasses,
102124
'dropdown-menu',
103-
this.right ? 'dropdown-menu-right' : 'dropdown-menu-left',
104125
{ 'show': this.visible }
105126
]
106-
}
127+
},
107128
},
129+
render (h) {
130+
const toggle = this.$slots.button || h(
131+
this.buttonTag,
132+
{
133+
style: { cursor: 'pointer' },
134+
attrs: {
135+
'aria-haspopup': true,
136+
'aria-expanded': this.visible,
137+
},
138+
on: {
139+
click: this.split ? '' : this.click
140+
},
141+
ref: 'toggle',
142+
class: this.computedButtonClasses,
143+
domProps: !this.$slots.buttonContent ?
144+
{ innerHTML: this.buttonContent } :
145+
null
146+
}, this.$slots.buttonContent)
147+
let splitButton = h(false)
148+
if (this.split) {
149+
splitButton = h(
150+
this.buttonTag,
151+
{
152+
class: [ this.computedButtonClasses, 'dropdown-toggle dropdown-toggle-split'],
153+
on: { click: this.click }
154+
})
155+
}
156+
157+
158+
const content = h(
159+
'div',
160+
{
161+
class: this.computedMenuClasses,
162+
ref: 'menu',
163+
directives: [{ name: 'on-clickaway', value: this.hide }],
164+
},
165+
this.$slots.default
166+
)
167+
return h(
168+
this.nav ? 'li' : 'div',
169+
{ class: this.computedDropdownClasses },
170+
[ toggle, splitButton, content ]
171+
)
172+
}
108173
}
109174
</script>

src/components/Dropdown/CDropdownItem.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import { mergeData } from 'vue-functional-data-merge'
2-
import CLink, { propsFactory as linkPropsFactory } from '../Link/CLink'
3-
4-
export const props = linkPropsFactory()
2+
import CLink, { propsFactory } from '../Link/CLink'
53

64
export default {
75
functional: true,
86
name: 'CDropdownItem',
9-
props,
7+
props: propsFactory(),
108
render (h, { props, data, children }) {
119
return h(
1210
CLink,

0 commit comments

Comments
 (0)