← Back to Demo Home

đŸŸĸ ModernToasts + Vue.js

Complete Vue.js integration with composables and plugins

🚀 Live Demo

Vue.js Interactive Demo

đŸ“Ļ Installation

npm install modern-toasts

đŸŽ¯ Basic Usage

Simple Import and Use

import toast from 'modern-toasts';

export default {
  methods: {
    handleClick() {
      toast.success('Hello from Vue!');
    }
  }
}

🔌 Vue Plugin

Create a Vue plugin for global access

// 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);
  }
};

Register the plugin

// 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');

Use in components (Options API)

export default {
  methods: {
    handleSave() {
      this.$toast.success('Data saved successfully!');
    },
    
    handleError() {
      this.$toast.error('Something went wrong!');
    }
  }
}

đŸŽŖ Composition API

Create a composable

// 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
  };
}

Use in components (Composition API)

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
    };
  }
}

🔄 Real-world Examples

Form Validation

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
    };
  }
}

API Integration with Loading States

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
    };
  }
}

Reactive Toast Configuration

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
    };
  }
}

🎭 Custom Toast Component

// 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>

Usage in templates

<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>

âš™ī¸ Advanced Configuration

// 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;
          }
        `
      });
    });
  }
}

📱 TypeScript Support

// 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
  };
}

🔗 Useful Links