A simple and flexible implementation of toast style notifications using Vue.js

Toast notifications are a user-friendly way to provide feedback or alert users to important events in a web application. In this comprehensive guide, we’ll explore the process of creating a simple and flexible implementation of toast-style notifications using Vue.js. Leveraging the reactivity and component-based structure of Vue.js, you’ll be able to seamlessly integrate toast notifications into your projects.

Introduction to Vue.js and Toast Notifications

Vue.js is a progressive JavaScript framework that excels at building user interfaces. Toast notifications, known for their unobtrusive appearance and brief display time, enhance user experience by providing real-time feedback. This guide will walk you through the step-by-step process of implementing toast notifications in Vue.js, offering flexibility and ease of use.

Setting Up the Vue.js Project

Start by initializing a new Vue.js project using the Vue CLI:

vue create vue-toast-notifications

Navigate to the project directory:

cd vue-toast-notifications

Install any additional dependencies you might need during the project, such as Vue CLI Service for development:

npm install @vue/cli-service --save

Designing the Toast Component

Create a modular Vue component to encapsulate the structure and functionality of the toast notifications. Let’s name it Toast.vue:

<!-- Toast.vue -->
<template>
  <div v-if="isVisible" class="toast" :class="[positionClass, typeClass]">
    {{ message }}
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true,
    },
    type: {
      type: String,
      default: 'info',
      validator: (value) => ['info', 'success', 'warning', 'error'].includes(value),
    },
    position: {
      type: String,
      default: 'top-right',
      validator: (value) => ['top-right', 'top-left', 'bottom-right', 'bottom-left'].includes(value),
    },
    duration: {
      type: Number,
      default: 3000,
    },
  },
  data() {
    return {
      isVisible: true,
    };
  },
  computed: {
    positionClass() {
      return `toast-${this.position}`;
    },
    typeClass() {
      return `toast-${this.type}`;
    },
  },
  mounted() {
    setTimeout(() => {
      this.isVisible = false;
    }, this.duration);
  },
};
</script>

<style scoped>
/* Component-specific styles here */
.toast {
  position: fixed;
  z-index: 1000;
  padding: 10px 20px;
  color: #fff;
  border-radius: 4px;
  transition: opacity 0.5s ease-in-out;
}

.toast-info {
  background-color: #3498db;
}

.toast-success {
  background-color: #2ecc71;
}

.toast-warning {
  background-color: #e67e22;
}

.toast-error {
  background-color: #e74c3c;
}

.toast-top-right {
  top: 20px;
  right: 20px;
}

.toast-top-left {
  top: 20px;
  left: 20px;
}

.toast-bottom-right {
  bottom: 20px;
  right: 20px;
}

.toast-bottom-left {
  bottom: 20px;
  left: 20px;
}
</style>

In this example, the Toast component includes dynamic classes based on props like type, position, and duration. The toast is automatically hidden after the specified duration.

Creating the ToastContainer Component

Now, let’s create a ToastContainer component that manages and displays multiple toasts. Create a new file named ToastContainer.vue:

<!-- ToastContainer.vue -->
<template>
  <div class="toast-container">
    <Toast v-for="toast in toasts" :key="toast.id" :message="toast.message" :type="toast.type" :position="toast.position" :duration="toast.duration" />
  </div>
</template>

<script>
import Toast from './Toast.vue';

export default {
  components: {
    Toast,
  },
  data() {
    return {
      toasts: [],
    };
  },
  methods: {
    addToast(message, type = 'info', position = 'top-right', duration = 3000) {
      const id = Date.now();
      this.toasts.push({ id, message, type, position, duration });

      setTimeout(() => {
        this.removeToast(id);
      }, duration + 500);
    },
    removeToast(id) {
      this.toasts = this.toasts.filter((toast) => toast.id !== id);
    },
  },
};
</script>

<style scoped>
/* Component-specific styles here */
.toast-container {
  position: fixed;
  z-index: 1000;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  padding: 20px;
  pointer-events: none;
}
</style>

The ToastContainer component manages an array of toasts and dynamically renders Toast components based on the array.

Incorporating the Toast Components into Your App

Integrate the ToastContainer component into your main application file (e.g., App.vue):

<!-- App.vue -->
<template>
  <div id="app">
    <button @click="showInfoToast">Show Info Toast</button>
    <button @click="showSuccessToast">Show Success Toast</button>
    <button @click="showWarningToast">Show Warning Toast</button>
    <button @click="showErrorToast">Show Error Toast</button>

    <ToastContainer />
  </div>


</template>

<script>
import ToastContainer from './components/ToastContainer.vue';

export default {
  components: {
    ToastContainer,
  },
  methods: {
    showInfoToast() {
      this.$refs.toastContainer.addToast('This is an Info Toast', 'info', 'top-right');
    },
    showSuccessToast() {
      this.$refs.toastContainer.addToast('Operation Successful!', 'success', 'top-left');
    },
    showWarningToast() {
      this.$refs.toastContainer.addToast('Warning: Proceed with caution', 'warning', 'bottom-right');
    },
    showErrorToast() {
      this.$refs.toastContainer.addToast('Error: Something went wrong', 'error', 'bottom-left');
    },
  },
};
</script>

<style>
/* Global styles here */
body {
  margin: 0;
  font-family: 'Arial', sans-serif;
  background-color: #f4f4f4;
}

#app {
  text-align: center;
  padding: 20px;
}

button {
  padding: 10px;
  font-size: 16px;
  margin: 10px;
}
</style>

In this example, the App component includes buttons to trigger different types of toasts. The ToastContainer component manages the display and removal of toasts.

If want to make a simple and flexible implementation of toast style notifications for Vue.js

then you can follow these steps to use this in your vue project

Features

  • Functional Stacking, Positioning, Timing & Dismissal API. Breadstick exposes a function that allows you to to control the stacking, positioning and dismissal of authored toast style notifications.
  • Render whatever you want. Utilize the render callback to create beautiful custom notifications.
  • Functional default styles. Import the provided css for some nice styling defaults or write your own styles.
  • Vue framework-agnostic notification. Breadstick is un-opininated about the styling of your Vue toast notifications. It’s main strengths are in handling the business logic of stacking, positioning, timing & dismissal of your toast notifications.

Installation

Install breadstick and its peer dependency, animejs, using yarn or npm.

npm install breadstick animejs --save

You can then register BreadstickBakery as a Vue plugin.

import Vue from 'vue'
import { BreadstickBakery } from 'breadstick'

// This exposes `this.$breadstick` in your Vue template.
Vue.use(BreadstickBakery)

Installing with Nuxt

After installing Breadstick, we import it and register it as a client-side plugin. This is because Breadstick it makes use of some DOM APIs. Code is similiar to the Vue plugin shown above

Examples

Breadstick can be used to render different types of notifications out of the box. You can render simple string notifications as well as custom styled notifications. This makes it really convenient.

Basic usage

Invoke a notification using the notify method to display a message to the user. Breadstick defaults the notification duration to 5 seconds in the top position.

this.$breadstick.notify('🥞 Show me the pancakes')

Using different positions

You can display notifications in different positions, including top-left, top, top-right, bottom-left, bottom, and bottom-right.

[
  'top-left', 
  'top', 
  'top-right', 
  'bottom-left', 
  'bottom', 
  'bottom-right'
].forEach(position => {
  this.$breadstick.notify("Using position " + position, {
    position
  })
})

🏠 Using custom element

With JSX or Vue’s render function, breadstick is able to render a custom element or Vue component

this.$breadstick.notify(
  <div>I am a custom HTML element</div>
)

🚚 With JSX

You can also use JSX if you like

// Import your custom `Alert` component and render it in breadstick
import Alert from './components/Alert'

export default {
  mounted () {
    breadstick.notify(({ onClose }) => {
      return (
        <Alert onClick={onClose}>
          An JSX Alert notification
        </Alert>
      )
    }
  }
}

Leave a Comment