Complete Vue.js integration with composables and plugins
npm install modern-toasts
import toast from 'modern-toasts';
export default {
methods: {
handleClick() {
toast.success('Hello from Vue!');
}
}
}
// plugins/toast.js
import toast from 'modern-toasts';
export default {
install(app, options = {}) {
// Configure toast with options
toast.configure({
position: 'bottom-right',
maxVisibleStackToasts: 3,
enableBorderAnimation: true,
enableFillAnimation: true,
...options
});
// Add to global properties
app.config.globalProperties.$toast = toast;
// Provide for composition API
app.provide('toast', toast);
}
};
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import ToastPlugin from './plugins/toast';
const app = createApp(App);
app.use(ToastPlugin, {
position: 'top-right',
maxVisibleStackToasts: 4
});
app.mount('#app');
export default {
methods: {
handleSave() {
this.$toast.success('Data saved successfully!');
},
handleError() {
this.$toast.error('Something went wrong!');
}
}
}
// composables/useToast.js
import { inject } from 'vue';
import toast from 'modern-toasts';
export function useToast() {
// Try to get from provide/inject first
const injectedToast = inject('toast', null);
const toastInstance = injectedToast || toast;
const showSuccess = (message, options) => {
return toastInstance.success(message, options);
};
const showError = (message, options) => {
return toastInstance.error(message, options);
};
const showInfo = (message, options) => {
return toastInstance.info(message, options);
};
const showWarning = (message, options) => {
return toastInstance.warning(message, options);
};
const dismiss = (id) => {
toastInstance.dismiss(id);
};
const dismissAll = () => {
toastInstance.dismissAll();
};
const configure = (config) => {
toastInstance.configure(config);
};
return {
showSuccess,
showError,
showInfo,
showWarning,
dismiss,
dismissAll,
configure,
toast: toastInstance
};
}
import { useToast } from '@/composables/useToast';
export default {
setup() {
const { showSuccess, showError } = useToast();
const handleSubmit = async () => {
try {
await submitForm();
showSuccess('Form submitted successfully!');
} catch (error) {
showError('Failed to submit form');
}
};
return {
handleSubmit
};
}
}
import { ref } from 'vue';
import { useToast } from '@/composables/useToast';
export default {
setup() {
const { showError, showSuccess } = useToast();
const form = ref({
email: '',
password: ''
});
const validateAndSubmit = async () => {
// Validation
if (!form.value.email) {
showError('Email is required');
return;
}
if (!form.value.password) {
showError('Password is required');
return;
}
if (form.value.password.length < 8) {
showError('Password must be at least 8 characters');
return;
}
try {
await login(form.value);
showSuccess('Login successful!', {
autoDismiss: 3000
});
} catch (error) {
showError('Invalid credentials');
}
};
return {
form,
validateAndSubmit
};
}
}
import { ref } from 'vue';
import { useToast } from '@/composables/useToast';
export default {
setup() {
const { showInfo, showSuccess, showError, dismiss } = useToast();
const loading = ref(false);
const data = ref(null);
const fetchData = async () => {
loading.value = true;
const loadingToastId = showInfo('Loading data...', {
autoDismiss: 0 // Keep until we dismiss it
});
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
data.value = await response.json();
// Dismiss loading toast and show success
dismiss(loadingToastId);
showSuccess('Data loaded successfully!');
} catch (error) {
dismiss(loadingToastId);
if (error.message.includes('404')) {
showError('Data not found');
} else if (error.message.includes('500')) {
showError('Server error. Please try again.');
} else {
showError('Network error. Check your connection.');
}
} finally {
loading.value = false;
}
};
return {
loading,
data,
fetchData
};
}
}
import { ref, watch } from 'vue';
import { useToast } from '@/composables/useToast';
export default {
setup() {
const { configure, showInfo } = useToast();
const position = ref('bottom-right');
const maxVisible = ref(3);
// Watch for configuration changes
watch([position, maxVisible], ([newPosition, newMaxVisible]) => {
configure({
position: newPosition,
maxVisibleStackToasts: newMaxVisible
});
showInfo(`Configuration updated: ${newPosition}, max ${newMaxVisible}`);
});
return {
position,
maxVisible
};
}
}
// components/ToastButton.vue
<template>
<button
@click="showToast"
:class="buttonClass"
:disabled="loading"
>
{{ loading ? 'Loading...' : label }}
</button>
</template>
<script>
import { useToast } from '@/composables/useToast';
export default {
props: {
label: String,
type: {
type: String,
default: 'info'
},
message: String,
loading: Boolean
},
setup(props) {
const { showSuccess, showError, showInfo, showWarning } = useToast();
const toastMethods = {
success: showSuccess,
error: showError,
info: showInfo,
warning: showWarning
};
const showToast = () => {
const method = toastMethods[props.type];
if (method) {
method(props.message || `${props.type} toast!`);
}
};
return {
showToast
};
},
computed: {
buttonClass() {
return `btn btn-${this.type}`;
}
}
}
</script>
<template>
<ToastButton
type="success"
message="Operation completed successfully!"
label="Complete Task"
:options="{ autoDismiss: 3000 }"
/>
<ToastButton
type="error"
message="Something went wrong!"
label="Trigger Error"
/>
</template>
// Configure globally or per component
import { useToast } from '@/composables/useToast';
import { onMounted } from 'vue';
export default {
setup() {
const { configure } = useToast();
// Configure on component mount
onMounted(() => {
configure({
position: 'top-center',
maxVisibleStackToasts: 5,
defaultDuration: 5000,
enableBorderAnimation: true,
enableFillAnimation: true,
pauseBackgroundToastsOnHover: true,
customCSS: `
.toast-container {
z-index: 9999;
}
`
});
});
}
}
// composables/useToast.ts
import { inject } from 'vue';
import toast, { ToastType, ToastOptions } from 'modern-toasts';
interface CustomToastOptions extends ToastOptions {
userId?: string;
component?: string;
}
export function useToast() {
const showTypedToast = (
type: ToastType,
message: string,
options?: CustomToastOptions
): string => {
return toast[type](message, options);
};
return {
showSuccess: (msg: string, opts?: CustomToastOptions) =>
showTypedToast('success', msg, opts),
showError: (msg: string, opts?: CustomToastOptions) =>
showTypedToast('error', msg, opts),
// ... other methods
};
}