DEV Community

WebCraft Notes
WebCraft Notes

Posted on • Originally published at webcraft-notes.com

Designing Responsive Modals and User Notifications for Nuxt.js E-commerce Platform

Designing Responsive Modals and User Notifications for Nuxt.js E-commerce Platform

Check this post in my web notes!

In our previous article, we finished creating our e-commerce store main pages, and now it's time to move further and add some dynamic elements like modals and notifications. First of all modal window, will be useful for product quick view, product management, etc., and the notifications role is crucial because it is the best way to communicate with the user, starting from welcome messages and finishing with sale messages. Yes, as you got from the intro and title our today's article will consist of the following:

  1. Creating Custom Modals in Nuxt.js
  2. Configuring Notification Messages in our E-commerce store

Now that we know how important modals and alerts are, let's study how to integrate them into our Nuxt.js e-commerce application and get into the implementation specifics.

1. Creating Custom Modals in Nuxt.js

We need to clarify that we want to create a reusable modal window so that it can be used in many ways and show different data. For that, we will create a main Modal component with modal-specific styles and items that could be rendered inside our modal component.

First things first, create a Modal.vue file inside the "ui" folder with a container that should blur the background and a modal div inside that will contain dynamically rendered items. Also, we will import the "xmark" icon and make it a button that will close our Modal window.

<template>
    <div class="container">
        <div class="modal">
            <div class="modal__close">
                <button class="modal__close--btn" @click="closeModal">
                    <NuxtIcon name="xmark-solid" class="modal__close--icon"/>
                </button>
            </div>
            <div class="modal__content">

            </div>
        </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Inside our base store, we will add two new variables "modalStatus" with a false value and "modalType" as a String, and add simple actions that will modify these values.

aSetModalStatus(status) {
    this.modalStatus = status;
},
aSetModalType(type) {
    this.modalType = type;
},
Enter fullscreen mode Exit fullscreen mode

The status variable will control modal render behavior and type will update different modal types.

Now, when we have a modal control system we can add our modal component to the default layout. Do not forget to import our base store.

<template>
    <div class="layout">
      <AppHeader />
          <slot />
    </div>
    <AppFooter />
    <Modal v-if="baseStore.gModalStatus"/>
</template>
Enter fullscreen mode Exit fullscreen mode

Great, our reusable modal component is ready, now if we want to show the modal we simply need to update the modalStatus value inside the base store.

Also, you can add whatever styles you want to the modal component, but I recommend you to use "Glassmorphism" and it will look stylish.

.container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 100;
    display: flex;
    justify-content: center;
    align-items: center;
    .modal {
        min-width: 300px;
        min-height: 300px;
        background: rgba( 255, 255, 255, 0.9 );
        box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 );
        backdrop-filter: blur( 13px );
        -webkit-backdrop-filter: blur( 13px );
        border-radius: 10px;
        border: 1px solid rgba( 255, 255, 255, 0.18 );
        padding: 24px;
        display: flex;
        flex-direction: column;
        &__close {
            display: flex;
            justify-content: flex-end;
            width: 100%;
            &--btn {
                border: none;
                background-color: transparent;
                cursor: pointer;
                outline: none;
                display: flex;
                align-items: center;
            }
            &--icon {
                color: #6c757d;
                font-size: 20px;
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We did a great job over here, but I'm offering you to continue and create the first component that will use our modal - "Product Preview", which will be available after the preview button clicks on any product card. Let's create a new Vue file inside the "common" folder and add some HTML/CSS elements:

<template>
    <div class="product-preview">
        <div class="product-preview__left">
            <div class="product-preview__left--image">
                <img src="../../assets/images/main/trend.jpg" alt="product image">
            </div>
        </div>
        <div class="product-preview__right">
            <p class="product-preview__right--name">Product Name</p>
            <p class="product-preview__right--price">$100</p>
            <p class="product-preview__right--text">Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur, ipsam! Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur, ipsam! Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur, ipsam!</p>
            <button class="product-preview__right--btn">Add to cart</button>
            <button class="product-preview__right--btn2">
                <NuxtIcon name="heart-regular" size="20" class="overlay__list--icon"/>
                Add to wishlist
            </button>
        </div>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Then import this component into Modal.vue file and insert it into the content div.

<div class="modal__content">
    <ProductPreview v-if="baseStore.modalType === 'product-preview'" />
</div>
Enter fullscreen mode Exit fullscreen mode

Now, we only need to add a function like "showPreview" to our card so that after the user clicks, that function will set the modal type to "product-preview" and the modal status to "true". That's it, we have a reusable modal and product preview functionality.
modal result
Okay, we need to move on and add alert messages to our Nuxt.js project.

2. Configuring Notification Messages in our E-commerce store

Okay, we can add something like a modal change its styles, and call it alerts, sounds like a simple and fast solution. But what if there will be triggered two or more alerts at the same time (for example "welcome" message and "your wishlist is not empty" message)? To solve this problem we will create an alert container that will be expanding as much as the number of incoming messages.

First of all, we will add alert settings to our store, similar to what we did with the modal part. Add the "notificationsList" array to the state part, and add notification actions that will push and remove the notification from the list. Each notification has a unique ID and shows status, type, message, and delay (amount of time that our message will be visible).

aSetNotification(payload) {
    const notification = {
        id: uuidv4(),
        show: true,
        type: payload.type,
        msg: payload.msg,
        delay: payload.delay ? payload.delay : 7000,
    }
    this.notificationsList.push(notification);
},
aRemoveNotification(id) {
    const indexToRemove = this.notificationsList.findIndex((element) => element.id === id);
    if (indexToRemove !== -1) {
        this.notificationsList.splice(indexToRemove, 1);
    }
},
Enter fullscreen mode Exit fullscreen mode

Next move, we need to create a "Notification" component that will render a message itself, depending on the message type. Also, we need to use delay time and remove messages automatically.

<template>
    <div class="animate__animated animate__backInRight" 
        v-if="notification.show">
        <div class="alert alert-success" v-if="notification.type === 'success'">
            <div class="icon__wrapper">
                <nuxt-icon name="exclamation-solid" />
            </div>
            <p class="notification__text">{{ notification.msg }}</p>
            <span class="close"
                @click.prevent="baseStore.aRemoveNotification(notification.id)">
                &times;
            </span>
        </div>
        <div class="alert alert-error" v-if="notification.type === 'error'">
            <div class="icon__wrapper">
                <nuxt-icon name="exclamation-solid" />
            </div>
            <p class="notification__text">{{ notification.msg }}</p>
            <span class="close"
                @click.prevent="baseStore.aRemoveNotification(notification.id)">
                &times;
            </span>
        </div>
    </div>
</template>

<script>
    import { useBaseStore } from '@/store/base';
    export default {
        name: 'MainNotification',
        props: {
            notification: {
                type: Object,
                required: true
            }
        },
        computed: {
            baseStore() {
                return useBaseStore();
            }
        },
        mounted() {
            setTimeout(() => {
                this.baseStore.aRemoveNotification(this.notification.id);
            }, this.notification.delay)
        }
    }
</script>
Enter fullscreen mode Exit fullscreen mode

You can style your messages in any way you want, I'll as usual use "Glassmorphism" and add some color.

.alert-success {
    background: rgba( 114, 255, 136, 0.45 );
    box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 );
    backdrop-filter: blur( 10px );
    -webkit-backdrop-filter: blur( 10px );
    border-radius: 10px;
    border: 1px solid rgba( 255, 255, 255, 0.18 );
}
Enter fullscreen mode Exit fullscreen mode

And final touch, we need to create our messages container and add that container into the app.vue file.

The notification container will simply render an array of our list that is stored in the base file.

<template>
    <div class="notification__container">
        <MainNotification v-for="(notification, index) of baseStore.gNotificationsList"
            :key="index"
            :notification="notification" />
    </div>
</template>

<script>
import { useBaseStore } from '@/store/base';
import MainNotification from './MainNotification.vue';

export default {
    name: 'NotificationContainer',
    components: {
        MainNotification,
    },
    computed: {
        baseStore() {
            return useBaseStore();
        }
    }
};
</script>
Enter fullscreen mode Exit fullscreen mode

Do not forget to add "Notification Container" to the main app.vue file.

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
  <NotificationContainer />
</template>
Enter fullscreen mode Exit fullscreen mode

That's it, we can restart our dev server and trigger notification messages a few times, just to check the result.
Nuxt js alert result
With the integration of modals and notifications, our Nuxt.js e-commerce application has become more dynamic, interactive, and user-friendly. These elements contribute to an enhanced shopping experience, enabling our customers to preview products and stay informed throughout their journey.

As we continue to build and improve our e-commerce platform, we can further expand the functionality of modals and notifications, tailoring them to specific use cases and ensuring a seamless and engaging experience for our users.

If you would need a source code for this tutorial you can get it here.

Top comments (0)