@xosen/vuetify-dialog
v0.1.0
Published
Vuetify 3 dialog system with alerts, snackbars, and async component support
Maintainers
Readme
@xosen/vuetify-dialog
A dialog, snackbar, and alert system for Vuetify 3. No <DialogContainer> in your template — dialogs render dynamically via Vue.render().
Installation
pnpm add @xosen/vuetify-dialogPeer dependencies: vue ^3.3.0, vuetify ^3.4.0.
Setup
import { createApp } from 'vue';
import { VuetifyDialog } from '@xosen/vuetify-dialog';
const app = createApp(App);
app.use(VuetifyDialog, {
locale: 'en', // 'en' | 'ru' | 'uk' | 'hu' — or a function: () => i18n.global.locale.value
formVariant: 'outlined', // default form field variant
formDensity: 'compact', // default form field density
});Usage
Composable (recommended)
import { useDialog } from '@xosen/vuetify-dialog';
const dialog = useDialog();Global property
// Options API
this.$dialog.confirm('Are you sure?');
// Template
$dialog.confirm('Are you sure?');Dialogs
confirm
const confirmed = await dialog.confirm('Delete this item?');
// confirmed === true | false
// With options
const confirmed = await dialog.confirm({
title: 'Delete Item',
text: 'This action cannot be undone.',
confirmText: 'Delete',
cancelText: 'Keep',
confirmColor: 'error',
cancelColor: 'secondary',
});info / success / warning / error
await dialog.info('Your session will expire soon.');
await dialog.success('Item saved.');
await dialog.warning('Low disk space.');
await dialog.error('Upload failed.');
// Custom title
await dialog.error('Connection timed out.', 'Network Error');create (full control)
const result = await dialog.create({
title: 'Choose action',
text: 'What would you like to do?',
html: '<p>Supports <strong>HTML</strong> content</p>', // alternative to text
actions: {
cancel: { text: 'Cancel', color: 'secondary' },
spacer: true, // pushes next actions to the right
delete: {
text: 'Delete',
color: 'error',
variant: 'elevated',
icon: 'mdi-delete',
onClick: async () => {
await api.deleteItem();
return 'deleted'; // returned as the dialog result
},
closeDialog: true, // default: true — set false to keep dialog open after click
},
},
dialogOptions: {
maxWidth: 500,
persistent: true, // block outside click
scrollable: true,
},
cardOptions: {
color: 'error',
},
});
// result === 'delete' (action key) or 'deleted' (onClick return value)show (custom component)
const result = await dialog.show(MyFormComponent, {
// props passed to the component
itemId: 123,
}, {
// dialog options
maxWidth: 600,
persistent: true,
});The component receives all props plus onCloseDialog. Emit close-dialog to close:
<script setup>
const emit = defineEmits(['close-dialog']);
function save(data) {
emit('close-dialog', data); // data becomes the dialog result
}
</script>Actions
Actions are defined as a Record<string, string | boolean | ActionConfig>:
interface ActionConfig {
text?: string | (() => string);
color?: string;
variant?: 'text' | 'flat' | 'elevated' | 'tonal' | 'outlined' | 'plain';
icon?: string | { name?: string; text?: string; right?: boolean };
size?: 'x-small' | 'small' | 'default' | 'large' | 'x-large';
block?: boolean;
disabled?: boolean | (() => boolean);
onClick?: (formData?, props?, actionKey?) => any | Promise<any>;
onError?: (error: unknown) => void; // called when onClick throws
closeDialog?: boolean; // default: true
}Shorthand forms:
actions: {
ok: 'OK', // string → { text: 'OK' }
spacer: true, // adds a v-spacer
save: { text: 'Save', color: 'primary', variant: 'elevated' },
}Snackbar
// Quick notifications (auto-dismiss after 5s)
await dialog.snackbar.info('Changes saved.');
await dialog.snackbar.success('Item created.');
await dialog.snackbar.warning('Rate limit approaching.');
await dialog.snackbar.error('Request failed.');
// Custom snackbar
await dialog.snackbar.show({
text: 'Custom message',
color: 'info',
timeout: 8000, // ms, -1 = no auto-dismiss
location: 'top right', // 'top' | 'bottom' | 'top left' | 'top right' | 'bottom left' | 'bottom right'
multiLine: true,
vertical: false,
elevation: 4,
variant: 'elevated',
rounded: true,
actions: { undo: { text: 'Undo', color: 'white', variant: 'text' } },
});
// Confirmation snackbar (no auto-dismiss)
const confirmed = await dialog.snackbar.confirm('Discard changes?', {
confirmText: 'Discard',
cancelText: 'Keep editing',
});Alert
Persistent, stackable alerts. Multiple alerts at the same location stack in a container.
// Quick alerts (auto-dismiss after 5s)
await dialog.alert.info('Deployment started.');
await dialog.alert.success('Build complete.');
await dialog.alert.warning('Certificate expires in 7 days.');
await dialog.alert.error('Pipeline failed.');
// Custom alert
await dialog.alert.show({
title: 'Update Available',
text: 'Version 2.0 is ready.',
html: '<p>Supports <em>HTML</em></p>',
type: 'info', // 'success' | 'info' | 'warning' | 'error'
color: 'blue',
icon: 'mdi-update', // string, or false to hide
closable: true,
prominent: true,
density: 'default', // 'default' | 'comfortable' | 'compact'
border: 'start', // boolean | 'start' | 'end' | 'top' | 'bottom'
variant: 'tonal',
elevation: 2,
timeout: 10000, // ms, -1 = no auto-dismiss
location: 'top right', // 'top' | 'bottom' | 'top left' | 'top right' | 'bottom left' | 'bottom right'
});Components
All components are exported for direct use:
import {
Dialog,
DialogCard,
DialogActions,
DialogAction,
Snackbar,
Alert,
AlertContainer,
} from '@xosen/vuetify-dialog';DialogCard
Standalone card with title, content, and actions — useful inside your own v-dialog:
<v-dialog v-model="open">
<DialogCard
title="Edit Item"
:actions="{ cancel: 'Cancel', spacer: true, save: { text: 'Save', color: 'primary' } }"
@action="onAction"
@loading="onLoading"
>
<MyForm />
</DialogCard>
</v-dialog>DialogActions
Action bar with loading states, usable standalone:
<DialogActions
:actions="{ cancel: 'Cancel', spacer: true, ok: { text: 'OK', color: 'primary' } }"
@action="(key, result) => handleAction(key, result)"
@loading="(isLoading) => handleLoading(isLoading)"
/>i18n
Built-in translations for button text: en, ru, uk, hu.
Static locale:
app.use(VuetifyDialog, { locale: 'uk' });Dynamic locale (reactive):
app.use(VuetifyDialog, { locale: () => i18n.global.locale.value });Region codes are normalized automatically: en-US -> en, uk-UA -> uk.
Module Federation
The plugin stores its config on window so it works across Module Federation boundaries. Remote apps can access useDialog() if the shell has installed the plugin.
Exports
// Plugin
export { VuetifyDialog, DialogPluginKey, getButtonText, getPluginConfig } from '@xosen/vuetify-dialog';
export type { VuetifyDialogOptions } from '@xosen/vuetify-dialog';
// Composable
export { useDialog } from '@xosen/vuetify-dialog';
// Components
export { Dialog, DialogCard, DialogActions, DialogAction, Snackbar, Alert, AlertContainer } from '@xosen/vuetify-dialog';
// Types
export type {
DialogOptions, ActionConfig, Actions, CustomComponent,
DialogInstance, ConfirmOptions, DialogPlugin,
SnackbarOptions, SnackbarPlugin, AlertOptions, AlertPlugin,
SupportedLocale,
} from '@xosen/vuetify-dialog';
// Constants
export { Z_INDEX_DIALOG_PICKER, Z_INDEX_ALERT, Z_INDEX_ALERT_CONTAINER } from '@xosen/vuetify-dialog';Related Packages
@xosen/vuetify-dialog-schema— Schema-based dialogs with form integration and wizards@xosen/vuetify-form— Standalone form builder
License
MIT
