-
-
Notifications
You must be signed in to change notification settings - Fork 7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Snackbar queue #2384
[Feature Request] Snackbar queue #2384
Comments
The reason for not currently supporting multiple snackbar messages is that MD spec specifies that only one snackbar should be displayed at a time. However, several people have made similar requests previously. And I think there is some merit to at least include basic support for displaying consecutive snackbar messages. Not a fan of providing a global queue in vuetify though. Will leave this open for discussion. |
One could create a component (say SnackDisplayer) and, using Vuex and stores, displaying the snackbar outside of any component (well... except the 1st level component containing the v-app tag). I tried this with a quite successful result. Here is a fiddle that demonstrate this: With this configuration (check fiddle source), one can call One thing that can be improved is indeed the possibility to have consecutive snackbars. |
I think it'd make sense to allow the |
So one way could be that they are queued and displayed one after another. But optional stacking would be cool as well. (Or maybe one message, but with a badge in the corner showing that there are many other pending behind this one.) Is there some other more MD-approved approach to display multiple messages to the user? |
The way Google applies the MD specs is closing the opened snackbar/toast when a new one is dispatched. You can see it in the new Google Calendar web version (more info), Angular Material and Angular Material2. |
I wrote a little mixin to provide a snackbar queue, it can be easily incorporated in your app: https://codepen.io/jayblanchard/pen/yoxPRY |
@Phlow2001, oh so easy. Thanks! I would love to also have a badge on the side of the snackbar, to show how many pending snackbars are in the queue, but it is not as easy as I expected: #2392 |
@Phlow2001 But your mixin does not align to the MD specs that @peluprvi mentioned.
|
@pschaub Based on the code of @Phlow2001, this code should aligns with the MD specs: addNotification(text) {
this.notification = false
setTimeout(() => {
this.notificationText = text
this.notification = true
}, 250)
} No snackbar queue, a new notification will replace the current one. Codepen: https://codepen.io/manuel-di-iorio/pen/YeyVMb |
I've been experimenting around with a queue system for the dialogs. I also want to spawn them programatically so here is what I have so far. Let it be an inspiration to whatever feature you guys are building, I'm not confident enough in it to PR it. index.js import Vue from 'vue'
import Toast from './Toast'
let queue = []
let showing = false
export { Toast }
export default {
open(params) {
if (!params.text) return console.error('[toast] no text supplied')
if (!params.type) params.type = 'info'
let propsData = {
title: params.title,
text: params.text,
type: params.type
}
let defaultOptions = {
color: params.type || 'info',
closeable: true,
autoHeight: true,
timeout: 1000,
multiLine: !!params.title || params.text.length > 80
}
params.options = Object.assign(defaultOptions, params.options)
propsData.options = params.options
// push into queue
queue.push(propsData)
processQueue()
}
}
function processQueue() {
if (queue.length < 1) return
if (showing) return
console.log(queue)
let nextInLine = queue[0]
spawn(nextInLine)
showing = true
queue.shift()
}
function spawn(propsData) {
const ToastComponent = Vue.extend(Toast)
return new ToastComponent({
el: document.createElement('div'),
propsData,
onClose: function() {
showing = false
processQueue()
}
})
} toast.vue <template>
<v-snackbar v-model="open" v-bind="options">
<div class="ctn">
<div class="title mb-2" v-if="title">{{title}}</div>
<div class="txt">{{text}}</div>
</div>
<v-btn v-if="options.closeable" flat icon @click.native="open = false">
<fai :icon="['fal', 'times']" size="lg"></fai>
</v-btn>
</v-snackbar>
</template>
<script>
/* TODO */
export default {
name: 'toast',
props: {
title: String,
text: String,
type: String,
options: Object,
},
data() {
return {
open: false,
}
},
watch: {
open: function(val) {
if (!val) {
this.close()
}
},
},
beforeMount() {
document.querySelector('#app').appendChild(this.$el)
},
mounted() {
this.open = true
},
methods: {
close() {
if (this.open) this.open = false
setTimeout(() => {
this.$options.onClose()
this.$destroy()
removeElement(this.$el)
}, 700) // wait for close animation
},
},
}
function removeElement(el) {
if (typeof el.remove !== 'undefined') {
el.remove()
} else {
el.parentNode.removeChild(el)
}
}
</script> main.js ...
import Toast from './components/toast'
Vue.prototype.$toast = Toast
... Then just use |
Another Mixin that somebody gave me on the discord channel, sorry I don't remember who
Usage: this.addNotification({text: 'Some Text', color: 'danger', timeout: 5000}) this.addNotification({text: 'Some Text', color: 'danger', timeout: 5000, top: false, bottom: true, multiline: true}) |
I have used this.$snackbar.open(`Default, positioned bottom-right with a green 'OK' button`) This can be triggered by any network call, vuex action, etc. |
@ankitsinghaniyaz my example is inspired by buefy, you can see the same index structure |
Agree to @ankitsinghaniyaz buefy has a nice implementation for this |
A couple of months ago I added a component to NPM that handles this and more. Here's a demo |
@Flamenco no github repo for it? |
@aldarund It's using a few of our internal libraries I can't open source at this moment; The binaries are free to distribute however. |
@Flamenco thanks, pretty nice. But hard to customize it. Such as change position, color etc. |
@raphaelsoul Some of those are on our wish list in the todo section of NPM. If I can get to it, I will post a github project to collect feature requests. What kind of API would you suggest for change position? |
@Flamenco cool demo, thanks for nice job! |
@shershen08 This is not open source yet. We have a collection of Vuetify utilities that will most likely be released under a CC license. |
I did a more or less simple CSS Hack i want to share if anybody feels like going in the same direction. WARNING this will brake vuetify default styling and possibility to change positioning the default way HTLM
SCSS
//vuex-store
//vuex-mutations
Global Access
//Usage in component
|
A long time ago I created package with do a lot and working as plugin. |
Published another stackable toast component if anyone's interested - https://vuetify-sonner.vercel.app |
To show all the snackbars in a stack way, please check : https://github.com/alihdev/vuetify-helper/blob/main/snackbars-stack-way.md |
Having this as an internal config would be really helpful. |
We are planning on experimenting with this now that 6c9eb7a is in. |
any update on this? |
Not planning work on this until after v3.4 (November) |
closes #2384 Co-authored-by: John Leider <john@vuetifyjs.com>
New Functionality
Currently it is not easy to handle interaction of multiple snackbar messages. They can overlap and hide each other. Moreover, because they are added as components inside other components, if parent component is removed (for example, because of a route change), snackbar message also disappears or is even not shown.
Improvements
I would propose that there is a global queue of snackbar messages. Maybe by sending a Vue event. Some options could then be to display messages one after the other, or display them stacked, up to some number.
Bugs or Edge Cases it Helps Avoid
Currently it seems one has to manually implement whole logic how to handle interaction between multiple snackbar messages.
EDIT: I have made a NPM package with this functionality @tozd/vue-snackbar-queue.
The text was updated successfully, but these errors were encountered: