Skip to content

Commit

Permalink
feat(QFab): add scoped slots for icon, icon-active and label quasarfr…
Browse files Browse the repository at this point in the history
  • Loading branch information
pdanpdan committed Dec 13, 2021
1 parent 44cdc60 commit 9d67d1b
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 23 deletions.
67 changes: 67 additions & 0 deletions docs/src/examples/QFab/FabSlots.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<template>
<div class="q-px-sm q-py-lg">
<div class="column items-center" style="margin-top: 100px; margin-bottom: 100px;">
<q-fab color="purple" direction="up">
<template v-slot:icon="{ opened }">
<q-icon :class="{ 'example-fab-animate--hover': opened !== true }" name="keyboard_arrow_up" />
</template>

<template v-slot:active-icon="{ opened }">
<q-icon :class="{ 'example-fab-animate': opened === true }" name="close" />
</template>

<q-fab-action color="primary" external-label @click="onClick">
<template v-slot:icon>
<q-icon name="mail" />
</template>
<template v-slot:label>
Mail
</template>
</q-fab-action>

<q-fab-action color="secondary" external-label @click="onClick" icon="alarm" label="Alarm" />
</q-fab>

<br>

<q-fab color="amber" text-color="black" icon="keyboard_arrow_left" direction="left">
<template v-slot:label="{ opened }">
<div :class="{ 'example-fab-animate--hover': opened !== true }">
{{ opened !== true ? 'Open' : 'Close' }}
</div>
</template>

<q-fab-action color="primary" @click="onClick" icon="mail" />
<q-fab-action color="secondary" @click="onClick" icon="alarm" />
</q-fab>
</div>
</div>
</template>

<script>
export default {
methods: {
onClick () {
// console.log('Clicked on a fab action')
}
}
}
</script>

<style lang="sass" scoped>
.example-fab-animate,
.q-fab:hover .example-fab-animate--hover
animation: example-fab-animate 0.82s cubic-bezier(.36,.07,.19,.97) both
transform: translate3d(0, 0, 0)
backface-visibility: hidden
perspective: 1000px
@keyframes example-fab-animate
10%, 90%
transform: translate3d(-1px, 0, 0)
20%, 80%
transform: translate3d(2px, 0, 0)
30%, 50%, 70%
transform: translate3d(-4px, 0, 0)
40%, 60%
transform: translate3d(4px, 0, 0)
</style>
6 changes: 6 additions & 0 deletions docs/src/pages/vue-components/floating-action-button.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ The default padding for QFab is "md" and for QFabAction is "sm". However, you ca

<doc-example title="Square style" file="QFab/SquareStyle" />

### Slots <q-badge align="top" color="brand-primary" label="v1.17+" />

Notice the slots for QFab and the slots for QFabAction below:

<doc-example title="Slots: icon, active-icon and label" file="QFab/FabSlots" />

### With QPageSticky

<doc-example title="With QPageSticky" file="QFab/PageSticky" />
Expand Down
57 changes: 54 additions & 3 deletions ui/dev/src/pages/components/fab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,42 @@
</q-fab-action>
</q-fab>

<div style="height: 1000px">
&nbsp;
</div>
<q-fab
class="fixed-bottom"
style="right: auto; bottom: 18px; left: 50%; transform: translateX(-50%)"
direction="up"
color="primary"
>
<template #icon="{ opened }">
<q-icon :class="{ 'test-fab-animate--hover': opened !== true }" :name="mdiMenu" />
</template>
<template #active-icon="{ opened }">
<q-icon :class="{ 'test-fab-animate': opened === true }" name="close" />
</template>
<template #label="{ opened }">
<div :class="{ 'test-fab-animate--hover': opened === true }">Label</div>
</template>

<q-fab-action color="blue" class="white" external-label>
<template #icon>
<q-icon name="person_add" />
</template>
<template #label>
Label
</template>

<q-tooltip anchor="center left" self="center right" :offset="[20, 0]">
Add person
</q-tooltip>
</q-fab-action>
<q-fab-action color="blue" class="white" icon="group_add">
<q-tooltip anchor="center left" self="center right" :offset="[20, 0]">
Add group
</q-tooltip>
</q-fab-action>
</q-fab>

<div style="height: 1000px">&nbsp;</div>

<div class="q-gutter-lg">
<q-btn fab :icon="mdiMenu" />
Expand Down Expand Up @@ -110,6 +143,24 @@
</div>
</template>

<style lang="sass">
.test-fab-animate,
.q-fab:hover .test-fab-animate--hover
animation: test-fab-animate 0.82s cubic-bezier(.36,.07,.19,.97) both
transform: translate3d(0, 0, 0)
backface-visibility: hidden
perspective: 1000px
@keyframes test-fab-animate
10%, 90%
transform: translate3d(-1px, 0, 0)
20%, 80%
transform: translate3d(2px, 0, 0)
30%, 50%, 70%
transform: translate3d(-4px, 0, 0)
40%, 60%
transform: translate3d(4px, 0, 0)
</style>

<script>
import { mdiMenu } from '@quasar/extras/mdi-v4'
Expand Down
31 changes: 20 additions & 11 deletions ui/src/components/fab/QFab.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export default Vue.extend({
'aria-haspopup': 'true',
...this.qAttrs
}
},

slotScope () {
return { opened: this.showing }
}
},

Expand All @@ -90,6 +94,15 @@ export default Vue.extend({
if (this.$refs.trigger && this.$refs.trigger.$el) {
this.$refs.trigger.$el.focus()
}
},

__getIcon (h, kebab, camel) {
const slotFn = this.$scopedSlots[kebab]
const staticClass = `q-fab__${kebab} absolute-full`

return slotFn === void 0
? h(QIcon, { staticClass, props: { name: this[kebab] || this.$q.iconSet.fab[camel] } })
: h('div', { staticClass }, slotFn(this.slotScope))
}
},

Expand All @@ -98,20 +111,16 @@ export default Vue.extend({

this.hideIcon !== true && child.push(
h('div', { staticClass: 'q-fab__icon-holder', class: this.iconHolderClasses }, [
h(QIcon, {
staticClass: 'q-fab__icon absolute-full',
props: { name: this.icon || this.$q.iconSet.fab.icon }
}),
h(QIcon, {
staticClass: 'q-fab__active-icon absolute-full',
props: { name: this.activeIcon || this.$q.iconSet.fab.activeIcon }
})
this.__getIcon(h, 'icon', 'icon'),
this.__getIcon(h, 'active-icon', 'activeIcon')
])
)

this.label !== '' && child[this.labelProps.action](
h('div', this.labelProps.data, [ this.label ])
)
if (this.label !== '' || this.$scopedSlots.label !== void 0) {
child[this.labelProps.action](
h('div', this.labelProps.data, this.$scopedSlots.label !== void 0 ? this.$scopedSlots.label(this.slotScope) : [ this.label ])
)
}

return h('div', {
staticClass: 'q-fab z-fab row inline justify-center',
Expand Down
33 changes: 33 additions & 0 deletions ui/src/components/fab/QFab.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,39 @@
}
},

"scopedSlots": {
"icon": {
"desc": "Slot for icon shown when FAB is closed; Suggestion: QIcon",
"scope": {
"opened": {
"type": "Boolean",
"desc": "FAB is opened"
}
},
"addedIn": "v1.17"
},
"active-icon": {
"desc": "Slot for icon shown when FAB is opened; Suggestion: QIcon",
"scope": {
"opened": {
"type": "Boolean",
"desc": "FAB is opened"
}
},
"addedIn": "v1.17"
},
"label": {
"desc": "Slot for label",
"scope": {
"opened": {
"type": "Boolean",
"desc": "FAB is opened"
}
},
"addedIn": "v1.17"
}
},

"events": {
"input": {
"desc": "Emitted when fab actions are shown/hidden; Captured by v-model directive"
Expand Down
25 changes: 16 additions & 9 deletions ui/src/components/fab/QFabAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,22 @@ export default Vue.extend({
render (h) {
const child = []

this.icon !== '' && child.push(
h(QIcon, {
props: { name: this.icon }
})
)

this.label !== '' && child[this.labelProps.action](
h('div', this.labelProps.data, [ this.label ])
)
if (this.$scopedSlots.icon !== void 0) {
child.push(this.$scopedSlots.icon())
}
else if (this.icon !== '') {
child.push(
h(QIcon, {
props: { name: this.icon }
})
)
}

if (this.label !== '' || this.$scopedSlots.label !== void 0) {
child[this.labelProps.action](
h('div', this.labelProps.data, this.$scopedSlots.label !== void 0 ? this.$scopedSlots.label() : [ this.label ])
)
}

return h(QBtn, {
class: this.classes,
Expand Down
10 changes: 10 additions & 0 deletions ui/src/components/fab/QFabAction.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@
"slots": {
"default": {
"desc": "Suggestion for this slot: QTooltip"
},

"icon": {
"desc": "Slot for icon; Suggestion: QIcon",
"addedIn": "v1.17"
},

"label": {
"desc": "Slot for label",
"addedIn": "v1.17"
}
},

Expand Down

0 comments on commit 9d67d1b

Please # to comment.