Last active
August 17, 2021 07:11
-
-
Save MichaelGitArt/68f86e0d553dcd4c6ac7a4eb678ba903 to your computer and use it in GitHub Desktop.
VuetifyDialog
This file contains 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> | |
<Component | |
:is="modal.component" | |
v-for="(modal, index) in dialogs" | |
:key="index" | |
:index="index" | |
v-bind="modal.props" | |
@close="onCloseModal(index)" | |
/> | |
</div> | |
</template> | |
<script> | |
import { mapState } from 'vuex'; | |
export default { | |
name: 'App', | |
computed: { | |
...mapState('core', ['dialogs']), | |
}, | |
methods: { | |
onCloseModal(index) { | |
this.$store.dispatch('core/hideDialog', index).then(() => { | |
setTimeout(() => { | |
this.$store.dispatch('core/removeDialog', index); | |
}, 100); | |
}); | |
}, | |
}, | |
}; | |
</script> |
This file contains 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="dialog-wrapper"> | |
<VDialog | |
:value="value" | |
:max-width="maxWidth" | |
:content-class="contentClasses" | |
:fullscreen="$vuetify.breakpoint.xsOnly && !disableFullscreen" | |
:persistent="persistent" | |
@input="onInput" | |
> | |
<div class="header"> | |
<slot name="toolbar" :scrolled="scrolled"> | |
<DialogDefaultToolbar | |
v-if="!disableDefaultToolbar" | |
:title="title" | |
:scrolled="scrolled" | |
@close="onClose" | |
> | |
<slot name="toolbar-title" /> | |
</DialogDefaultToolbar> | |
</slot> | |
</div> | |
<div | |
v-scroll.self="onScroll" | |
class="body" | |
:class="{ | |
'px-sm-8 px-4 pb-4': !disablePadding | |
}" | |
> | |
<slot /> | |
</div> | |
<div v-if="$slots['footer']" class="footer"> | |
<slot name="footer" /> | |
</div> | |
</VDialog> | |
</div> | |
</template> | |
<script> | |
import DialogDefaultToolbar from './DialogDefaultToolbar.vue'; | |
export default { | |
name: 'DialogDefault', | |
components: { | |
DialogDefaultToolbar, | |
}, | |
props: { | |
/** | |
* The dialog state | |
*/ | |
value: { | |
type: Boolean, | |
default: true, | |
}, | |
/** | |
* Dialog title in the default toolbar | |
*/ | |
title: { | |
type: String, | |
default: '', | |
}, | |
/** | |
* Max width of the dialog | |
*/ | |
maxWidth: { | |
type: [Number, String], | |
default: 480, | |
}, | |
/** | |
* Clicking outside of the dialog does not close it | |
*/ | |
persistent: { | |
type: Boolean, | |
default: false, | |
}, | |
/** | |
* Disable main slot padding | |
*/ | |
disablePadding: { | |
type: Boolean, | |
default: false, | |
}, | |
/** | |
* Disable default toolbar | |
*/ | |
disableDefaultToolbar: { | |
type: Boolean, | |
default: false, | |
}, | |
/** | |
* Disable default padding on the sides of the modal | |
*/ | |
disableFullscreen: { | |
type: Boolean, | |
default: false, | |
}, | |
contentClass: { | |
type: String, | |
default: '', | |
}, | |
}, | |
data: () => ({ | |
scrolled: false, | |
closed: false, | |
}), | |
computed: { | |
contentClasses() { | |
return `dialog-default ${this.contentClass}`; | |
}, | |
}, | |
methods: { | |
onScroll(e) { | |
this.scrolled = e.target.scrollTop > 0; | |
}, | |
onInput(value) { | |
if (!value && !this.closed) { | |
this.closed = true; | |
this.onClose(); | |
} | |
}, | |
onClose() { | |
this.$emit('close'); | |
this.$emit('input', false); | |
}, | |
}, | |
}; | |
</script> | |
<style lang="scss" scoped> | |
// eslint-disable-next-line vue-scoped-css/require-v-deep-argument | |
::v-deep { | |
.dialog-default { | |
display: flex; | |
flex-direction: column; | |
background-color: #fff; | |
.header { | |
flex-grow: 0; | |
z-index: 2; | |
} | |
.body { | |
overflow-x: hidden; | |
overflow-y: auto; | |
flex-grow: 1; | |
} | |
.footer { | |
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.2) !important; | |
flex-grow: 0; | |
z-index: 2; | |
} | |
} | |
} | |
</style> |
This file contains 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> | |
<VToolbar | |
color="#f5f4fa" | |
class="dialog-toolbar pl-sm-4" | |
:class="{ | |
'dialog-toolbar--scrolled': scrolled, | |
}" | |
> | |
<slot> | |
<VToolbarTitle> | |
{{ title }} | |
</VToolbarTitle> | |
</slot> | |
<VSpacer /> | |
<VBtn | |
rounded | |
icon | |
@click="onClose" | |
> | |
<VIcon>mdi-close</VIcon> | |
</VBtn> | |
</VToolbar> | |
</template> | |
<script> | |
export default { | |
name: 'DialogDefaultToolbar', | |
props: { | |
/** | |
* Dialog title | |
*/ | |
title: { | |
type: String, | |
default: '', | |
}, | |
/** | |
* Determines whether the dialog content is scrolled | |
*/ | |
scrolled: { | |
type: Boolean, | |
required: true, | |
}, | |
}, | |
methods: { | |
onClose() { | |
this.$emit('close') | |
}, | |
}, | |
} | |
</script> | |
<style lang="scss" scoped> | |
.dialog-toolbar { | |
box-shadow: none !important; | |
z-index: 2; | |
flex-grow: 0; | |
&--scrolled { | |
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.08) !important; | |
} | |
} | |
</style> |
This file contains 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
const state = () => ({ | |
dialogs: [], | |
}) | |
const actions = { | |
/** | |
* open a dialog | |
* @param {Object} context | |
* @param {Object} payload | |
* @param {Object} payload.component dialog component | |
* @param {Object} [payload.props] props for the component | |
*/ | |
addDialog({ commit }, payload) { | |
commit('addDialog', { | |
...payload, | |
props: { | |
...payload.props, | |
value: true, | |
}, | |
}); | |
}, | |
/** | |
* remove dialog | |
*/ | |
removeDialog({ commit }, index) { | |
commit('removeDialog', index); | |
}, | |
/** | |
* hide dialog before removing | |
*/ | |
hideDialog({ commit }, index) { | |
commit('hideDialog', index); | |
}, | |
} | |
const mutations = { | |
addDialog(state, modal) { | |
state.dialogs.push(modal); | |
}, | |
removeDialog(state, index) { | |
state.dialogs.splice(index, 1); | |
}, | |
hideDialog(state, index) { | |
state.dialogs[index].props.value = false; | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment