Logo

dev-resources.site

for different kinds of informations.

Global toast in Vue3

Published at
4/18/2024
Categories
vue
vue3
component
composable
Author
heliomsolivas
Categories
4 categories in total
vue
open
vue3
open
component
open
composable
open
Author
13 person written this
heliomsolivas
open
Global toast in Vue3

Hi there.

Today I will share the way I built a simple Toast component using Vue3 composables.

Recently, I had to create a project from scratch using Nuxt3 + TailwindCSS. In the middle of it, I needed a simple Toast component to handle some actions. So, after some research, I ended up with this component.

1- Creating the Toast component involves a bit of styling with TailwindCSS classes and custom CSS to control how the Toast appears.

Toast.vue

<script setup lang="ts">
defineProps({
    message: {
        required: false,
        type: String,
    },
    visibility: {
        required: true,
        type: Boolean,
    },
})
</script>

<template>
    <div v-if="visibility"
        class="toast z-50 fixed top-4 right-4 flex items-center gap-4 mb-4 text-gray-200 transition-all duration-[3000ms] w-80 overflow-hidden">
        <div class="p-3 w-full rounded-tl-none rounded-bl-none">
            <div class="flex items-center w-full">
                <div class="flex flex-col">
                    <div class="toast__title text-sm text-green-800">Success</div>
                    <div class="toast__text text-sm text-green-500">{{ message }}</div>
                </div>
            </div>
        </div>
    </div>
</template>

<style scoped>
.toast {
    box-shadow: 0px 4px 14px 0px rgba(0, 0, 0, 0.18);
    border-radius: 5px 0px 0px 5px;
    border-left: 7px solid #1fac66;
    width: 429px;
}
</style>

Enter fullscreen mode Exit fullscreen mode

2- Creating the composable
I've created two functions to handle the logic of the Toast component: one to add the message inside the component and another to reset it. I'm also using the useState composable from Nuxt to keep the variables visibility and messages available.

useToast.ts

export function useToast() {
    let visibility = useState('visibility', () => false)
    let messages = useState<string[]>('messages', () => [])

    function resetMessages() {
        messages.value = []
    }

    function addMessage(message: string) {
        if (message) {
            messages.value.push(message)
            visibility.value = true
            setTimeout(() => {
                visibility.value = false
                resetMessages()
            }, 3000)
        }
    }

    return {
        messages,
        addMessage,
        visibility,
    }
}

Enter fullscreen mode Exit fullscreen mode

3- In the root component of the project (app.vue in my case), I import the component and the composable to work together. In this example, there are some extras that I added for layout purposes:

app.vue

<script setup lang="ts">
const { messages, visibility } = useToast()
</script>
<template>
  <NuxtLayout>
    <NuxtPage></NuxtPage>
  </NuxtLayout>

  <TransitionGroup name="toast">
    <Toast v-for="(message, index) in messages" :key="index" :message="message" :index="index"
      :visibility="visibility" />
  </TransitionGroup>
</template>

<style>
.toast-enter-from,
.toast-leave-to {
  opacity: 0;
  transform: translateY(-60px);
}

.toast-enter-to,
.toast-leave-from {
  opacity: 1;
  transform: translateY(0);
}

.toast-enter-active,
.toast-leave-active {
  transition: all 0.3s ease;
}
</style>

Enter fullscreen mode Exit fullscreen mode

4- To see it working, you can simply call it from any page or component that you need. Here are two examples:

  • To trigger the modal from a page, you can use the following code:

index.vue

<script setup lang="ts">
const { addMessage } = useToast()

function triggerModal() {
    addMessage('My Amazing modal from Index.vue')
}
</script>

<template>
    <div>
        <div>This is my <b>index.vue</b> page</div>
        <button @click="triggerModal()">Trigger Modal</button>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Toast from page

  • To trigger the modal from a random component, you can use the following code:

myRandomComponent.vue

<script setup lang="ts">
const { addMessage } = useToast()

function triggerModal() {
    addMessage('My Amazing from component')
}
</script>
<template>
    <div>
        <div>My test component</div>
        <button @click="triggerModal()">Trigger Modal from my Component</button>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Toast from component

If you have any suggestions, please let me know. Thank you so much for reading!

component Article's
30 articles in total
Favicon
Build a note app with JavaScript component.
Favicon
Key characteristic of Component-Based Architecture
Favicon
React Component Libraries: Overview of 19 Top Libs
Favicon
Styling Components in React 🧢
Favicon
Building a Seamless OTP Input Field in React: A Step-by-Step Guide
Favicon
MithrilJS component with state management
Favicon
[Off Topic] Nano introdução do framework Angular para Devs do back
Favicon
Comparing Vue Component Documentation tools
Favicon
Laravel 11 Custom Component File Structure
Favicon
Building Message Component in Vue3
Favicon
Aplicando paginação em um componente Select
Favicon
How much does it cost to repair an outdoor LED display?
Favicon
Global toast in Vue3
Favicon
Unveiling the Hidden Gem of React: The Power of Compound Components
Favicon
Controlled vs Uncontrolled Components in React
Favicon
React components -(Class component v/s function component)
Favicon
3 Ways to Create React Components with Bit
Favicon
Client or Server component ?
Favicon
Desenvolvimento de Componentes Assíncronos com Vue.js
Favicon
NAND Flash vs NOR Flash: Differences between them
Favicon
Link Component in React Router
Favicon
Guia de Components - para quem tem pressa!
Favicon
How to exchange data between Angular components
Favicon
Component Testing with Cypress and Reactjs
Favicon
React - Higher Order Components (HOC)
Favicon
How to Create Component Library Like Material UI or Mantine UI?
Favicon
Looking forward to adding Algolia's DOCSEARCH to Mantine DataTable
Favicon
Cypress Component Testing vs React Testing Library - the complete comparison
Favicon
Creating Custom Component for NPS Feedback
Favicon
Maximize your Angular code reusability using <NgTemplateOutlet>

Featured ones: