Skip to content

Commit 5b58e19

Browse files
committed
feat: Improve QCollapsible (custom header, right side header items)
1 parent 55a4746 commit 5b58e19

File tree

4 files changed

+196
-144
lines changed

4 files changed

+196
-144
lines changed

dev/components/components/collapsible.vue

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,20 @@
44
<q-page padding style="max-width: 600px;">
55
<q-list>
66
{{ model }}
7-
<q-collapsible v-model="model" icon="explore" label="With model">
7+
<q-collapsible v-model="model" icon="explore" right-icon="map" label="With model">
8+
<div>
9+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
10+
</div>
11+
</q-collapsible>
12+
<q-collapsible>
13+
<template slot="header">
14+
<q-item-side icon="map" />
15+
<q-item-main label="Custom header" />
16+
<q-item-side right>
17+
<q-item-tile label>Custom</q-item-tile>
18+
</q-item-side>
19+
</template>
20+
821
<div>
922
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
1023
</div>
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { QItem, QItemSide, QItemTile, QItemWrapper } from '../list'
2+
import { QSlideTransition } from '../slide-transition'
3+
import Ripple from '../../directives/ripple'
4+
import ModelToggleMixin from '../../mixins/model-toggle'
5+
6+
const eventName = 'q:collapsible:close'
7+
8+
export default {
9+
name: 'q-collapsible',
10+
mixins: [ModelToggleMixin],
11+
modelToggle: {
12+
history: false
13+
},
14+
directives: {
15+
Ripple
16+
},
17+
props: {
18+
disable: Boolean,
19+
indent: Boolean,
20+
group: String,
21+
iconToggle: Boolean,
22+
separator: Boolean,
23+
insetSeparator: Boolean,
24+
noRipple: Boolean,
25+
26+
dense: Boolean,
27+
sparse: Boolean,
28+
multiline: Boolean,
29+
30+
icon: String,
31+
rightIcon: String,
32+
image: String,
33+
rightImage: String,
34+
avatar: String,
35+
rightAvatar: String,
36+
letter: String,
37+
rightLetter: String,
38+
label: String,
39+
sublabel: String,
40+
labelLines: [String, Number],
41+
sublabelLines: [String, Number]
42+
},
43+
computed: {
44+
cfg () {
45+
return {
46+
link: !this.iconToggle,
47+
headerStyle: [Array, String, Object],
48+
headerClass: [Array, String, Object],
49+
50+
dark: this.dark,
51+
dense: this.dense,
52+
sparse: this.sparse,
53+
multiline: this.multiline,
54+
55+
icon: this.icon,
56+
rightIcon: this.rightIcon,
57+
image: this.image,
58+
rightImage: this.rightImage,
59+
avatar: this.avatar,
60+
rightAvatar: this.rightAvatar,
61+
letter: this.letter,
62+
rightLetter: this.rightLetter,
63+
64+
label: this.label,
65+
sublabel: this.sublabel,
66+
labelLines: this.labelLines,
67+
sublabelLines: this.sublabelLines
68+
}
69+
},
70+
hasRipple () {
71+
return __THEME__ === 'mat' && !this.noRipple
72+
}
73+
},
74+
watch: {
75+
showing (val) {
76+
if (val && this.group) {
77+
this.$root.$emit(eventName, this)
78+
}
79+
}
80+
},
81+
methods: {
82+
__toggleItem () {
83+
if (!this.iconToggle) {
84+
this.toggle()
85+
}
86+
},
87+
__toggleIcon (e) {
88+
if (this.iconToggle) {
89+
e && e.stopPropagation()
90+
this.toggle()
91+
}
92+
},
93+
__eventHandler (comp) {
94+
if (this.group && this !== comp && comp.group === this.group) {
95+
this.hide()
96+
}
97+
},
98+
__getToggleSide (h, slot) {
99+
return [
100+
h(QItemTile, {
101+
slot: slot ? 'right' : undefined,
102+
staticClass: 'cursor-pointer transition-generic',
103+
'class': {
104+
'rotate-180': this.showing,
105+
invisible: this.disable
106+
},
107+
on: {
108+
click: this.__toggleIcon
109+
},
110+
props: { icon: 'keyboard_arrow_down' },
111+
directives: this.iconToggle && this.hasRipple
112+
? [{ name: 'ripple', value: !this.disable }]
113+
: []
114+
})
115+
]
116+
},
117+
__getItemProps (wrapper) {
118+
return {
119+
props: wrapper
120+
? { cfg: this.cfg }
121+
: { link: !this.iconToggle },
122+
style: this.headerStyle,
123+
'class': this.headerClass,
124+
on: {
125+
click: this.__toggleItem
126+
},
127+
directives: this.hasRipple && !this.iconToggle
128+
? [{ name: 'ripple', value: !this.disable }]
129+
: []
130+
}
131+
}
132+
},
133+
created () {
134+
this.$root.$on(eventName, this.__eventHandler)
135+
if (this.value) {
136+
this.show()
137+
}
138+
},
139+
beforeDestroy () {
140+
this.$root.$off(eventName, this.__eventHandler)
141+
},
142+
render (h) {
143+
return h('div', {
144+
staticClass: 'q-collapsible q-item-division relative-position',
145+
'class': {
146+
'q-item-separator': this.separator,
147+
'q-item-inset-separator': this.insetSeparator,
148+
disabled: this.disable
149+
}
150+
}, [
151+
this.$slots.header
152+
? h(QItem, this.__getItemProps(), [
153+
this.$slots.header,
154+
h(QItemSide, { props: { right: true } }, this.__getToggleSide(h))
155+
])
156+
: h(QItemWrapper, this.__getItemProps(true), this.__getToggleSide(h, true)),
157+
158+
h(QSlideTransition, [
159+
h('div', {
160+
directives: [{ name: 'show', value: this.showing }]
161+
}, [
162+
h('div', {
163+
staticClass: 'q-collapsible-sub-item relative-position',
164+
'class': { indent: this.indent }
165+
}, [
166+
this.$slots.default
167+
])
168+
])
169+
])
170+
])
171+
}
172+
}

src/components/collapsible/QCollapsible.vue

Lines changed: 0 additions & 131 deletions
This file was deleted.

src/components/list/QItemWrapper.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,19 @@ function push (child, h, name, slot, replace, conf) {
99
child.push(h(name, defaultProps, slot))
1010
return
1111
}
12-
let props, v = false
13-
if (!slot) {
14-
for (let p in conf) {
15-
if (conf.hasOwnProperty(p)) {
16-
v = conf[p]
17-
if (v !== void 0 && v !== true) {
18-
props = true
19-
break
20-
}
12+
13+
let v = false
14+
for (let p in conf) {
15+
if (conf.hasOwnProperty(p)) {
16+
v = conf[p]
17+
if (v !== void 0 && v !== true) {
18+
child.push(h(name, { props: conf }))
19+
break
2120
}
2221
}
2322
}
24-
if (props || slot) {
25-
child.push(h(name, props ? {props: conf} : defaultProps, slot))
26-
}
23+
24+
slot && child.push(h(name, defaultProps, slot))
2725
}
2826

2927
export default {

0 commit comments

Comments
 (0)