Vuetify 3 – Feedback (Dialog, Snackbar, Alert)
v-dialog
<template>
<v-btn @click="open = true">Edit user</v-btn>
<v-dialog v-model="open" max-width="500" persistent>
<v-card>
<v-card-title>Edit user</v-card-title>
<v-card-text>
<v-text-field v-model="form.name" label="Name" />
<v-text-field v-model="form.email" label="Email" />
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn variant="text" @click="open = false">Cancel</v-btn>
<v-btn color="primary" @click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
persistent: clicking the backdrop or pressing Esc does not close it. Use for unsaved-change scenarios.fullscreen: full-screen modal, useful on mobile.scrollable: when paired with<v-card>,<v-card-text>becomes internally scrollable while header/footer stay fixed.
Confirm-style dialog as a reusable component
<!-- ConfirmDialog.vue -->
<template>
<v-dialog v-model="show" max-width="420" persistent>
<v-card>
<v-card-title>{{ title }}</v-card-title>
<v-card-text>{{ message }}</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn variant="text" @click="answer(false)">Cancel</v-btn>
<v-btn color="primary" @click="answer(true)">Confirm</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
data() {
return { show: false, title: '', message: '', resolve: null }
},
methods: {
open({ title, message }) {
this.title = title
this.message = message
this.show = true
return new Promise((resolve) => { this.resolve = resolve })
},
answer(value) {
this.show = false
this.resolve(value)
},
},
}
</script>
Used like:
async deleteUser(user) {
const ok = await this.$refs.confirm.open({
title: 'Delete user',
message: `Delete ${user.name}? This cannot be undone.`,
})
if (ok) await api.delete(`/users/${user.id}`)
}
v-snackbar
For transient feedback ("Saved", "Error", etc.).
<template>
<v-snackbar v-model="snack.show" :color="snack.color" :timeout="3000">
{{ snack.text }}
<template #actions>
<v-btn variant="text" @click="snack.show = false">Close</v-btn>
</template>
</v-snackbar>
</template>
<script>
export default {
data() {
return { snack: { show: false, text: '', color: 'success' } }
},
methods: {
notify(text, color = 'success') {
this.snack = { show: true, text, color }
},
},
}
</script>
A common pattern is to put this snackbar in App.vue and trigger it from a
Pinia store (useNotifyStore) so any component can call
notify.show('Saved').
v-alert
For inline, non-transient messages (validation summaries, banner warnings).
<v-alert type="error" variant="tonal" closable>
Could not save changes — server returned 500.
</v-alert>
<v-alert type="info" variant="outlined" title="Heads up" text="Your session expires in 5 minutes." />
type (sets icon + color): success, info, warning, error.
variant: flat, elevated, tonal (lighter background), outlined, text.
v-progress-linear / v-progress-circular
<!-- indeterminate -->
<v-progress-linear indeterminate color="primary" />
<!-- value-driven -->
<v-progress-linear :model-value="uploadPct" color="success" height="8" />
<!-- circular -->
<v-progress-circular indeterminate :size="48" color="primary" />
Pair with :loading="loading" on <v-btn> for "saving…" states:
<v-btn color="primary" :loading="saving" @click="save">Save</v-btn>