How to Build a Modal Component in Vue.JS

The purpose of modals in Vuejs development services refers to a common practice in user interface design that draws the user’s attention to some information that needs to be read or interacted with. These often appear as discrete sections of text in the user’s line of sight, with the remainder of the page’s text masked or hidden by a solid background. To exit the modal and return to the website, the user must take some action. This tutorial will teach you how to use Vue.js’s transitions and slots to build a reusable VueJs modal component.

1. How To Build a Modal Component in VueJS?

1.1 Prerequisites

The following elements are required to finish this guide:

You can set up Node.js locally and Create a Local Development Environment.

1.2 Creating the Modal Component

Make a new file in the components folder and name it Modal.vue.

The next line of code will be:

<template>
 <div>
  <div v-if="isOpen">
   <h1>New Modal </h1>
   <p>This my first modal</p>
  </div>
  <button @click="isOpen=!isOpen">Show Modal</button>
 </div>
</template>
 
<script>
 export default {
  data() {
   return {
    isOpen: false
   };
  }
 }
</script>

HTMLCopy

Here, with just two div elements and a button, we were able to make our modal form. Clicking the button will bring up our modal.

Our modal will only show up if the isOpen value is true, so we added a v-if=isOpen directive to our second div element.

Let’s import our modal component into the App.vue file and put it through its paces; we’ll take care of the styling and transitions afterward.

You can open the modal window by toggling the Open modal button.

To add and erase transitions from HTML components, Vue provides a specialized transition element.

Let’s give our Modal element some flair by customizing its styles and transitions.

<template>
 <div>
 <transition name="modal">
 <div v-if="isOpen">
 <div class="overlay" @click.self="isOpen = false;">
 <div class="modal">
 <h1>New Modal </h1>
 <p>This my first modal</p>
 </div>
 </div>
 </div>
 </transition>
 <button @click="isOpen = !isOpen">
 {{ isOpen ? "Close" : "Open" }} Modal
 </button>
 </div>
</template>
 
<script>
 export default {
  data: function() {
   return {
    isOpen: false
   };
  }
};
</script>
 
<style scoped>
.modal {
font-family: Helvetica, Arial, sans-serif;
 
 margin: 0px auto;
 padding: 25px;
 width: 500px;
 background-color: #fff;
 border-radius: 3px;
 box-shadow: 0 2px 8px 3px;
 transition: all 0.2s ease-in;
 
}
.fadeIn-enter {
 opacity: 0;
}
 
.fadeIn-leave-active {
 opacity: 0;
 transition: all 0.2s step-end;
}
 
.fadeIn-enter .modal,
.fadeIn-leave-active.modal {
 transform: scale(1.1);
}
button {
 padding: 8px;
 margin-top: 11px;
color: white; 
background-color: green;
 
 font-size: 1.3rem;
}
 
.overlay {
 position: fixed;
width: 100%;
left: 0;
 top: 0;
 
 display: flex;
 justify-content: center;
 align-items: center;
 
 height: 100%;
 background: #000000;
 z-index: 1000;
 transition: opacity 0.2s ease;
}
</style>

1.3 Adding Styles and Transitions

Vue provides its users with a specialized transition element that can be used to build and remove transitions from HTML elements.

Let’s give our Modal widget some visual flair and smooth transitions.

Modal.vue

<template>
  <div>
 
   <transition name="modal">
     <div v-if="isOpen">
        <div class="overlay" @click.self="isOpen = false">
          <div class="modal">
            <h1>New Modal </h1>
            <p>This my first modal</p>
          </div>
        </div>
      </div>
    </transition>
    <button @click="isOpen = !isOpen;">
      {{ isOpen ? "Close" : "Open" }} Modal
    </button>
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      isOpen: false
    };
  }
};
</script>
 
<style scoped>
.modal {
  font-family: Helvetica, Arial, sans-serif;
  width: 600px;
  margin: 0px auto;
  padding: 25px;
  background-color: #ffffff;
  border-radius: 3px;
  box-shadow: 0 3px 9px 4px;
  transition: all 0.2s ease-in;
 
}
.fadeIn-enter {
  opacity: 0;
}
 
.fadeIn-leave-active {
  opacity: 0;
  transition: all 0.2s step-end;
}
 
.fadeIn-enter .modal,
.fadeIn-leave-active.modal {
  transform: scale(1.1);
}
 
button {
  padding: 8px;
  margin-top: 11px;
  background-color: green;
  color: white;
  font-size: 1.2rem;
}
 
.overlay {
  position: fixed;
    left: 0;
top: 0;
 
  display: flex;
 align-items: center;
  justify-content: center;
    width: 100%;
  height: 100%;
  background: #000000;
  z-index: 1000;
  transition: opacity 0.2s ease;
}
</style>

1.4 Adding Accessibility

  • Add ARIA properties to your modal component to make it available to everyone.
  • Including role=”dialog” will help assistive technologies recognize the element as a standalone dialog within the program rather than a part of the main user interface.
  • You must also include a suitable label with aria-labelledby and aria-describedby properties.
  • To make the close buttons more accessible, add aria-label attributes.

src/components/Modal.vue

<template>
  <transition name="fade-modal">
    <div class="backdrop-modal">
      <div class="modal"
        role="dialog"
        aria-labelledby="modalTitle"
        aria-describedby="modalDescription"
      >
        <header
          class="modal-header"
          id="modalTitle"
        >
          <slot name="header">
            Modal Title!
          </slot>
          <button
            type="button"
            class="btn-close"
            @click="close"
            aria-label="Close Modal"
          >
            x
          </button>
        </header>
 
        <section
          class="modal-body"
          id="modalDescription"
        >
          <slot name="body">
            This is the default body!
          </slot>
        </section>
 
        <footer class="modal-footer">
          <slot name="footer">
            This is the default footer!
          </slot>
          <button
            type="button"
            class="green-btn"
            @click="close"
            aria-label="Close modal"
          >
            Close Modal
          </button>
        </footer>
      </div>
    </div>
  </transition>
</template>

Copy

The final form of the modal part should look something like this:

src/components/Modal.vue

<script>
  export default {
    name: 'Modal',
    methods: {
      close() {
        this.$emit('close');
      },
    },
  };
</script>
 
<template>
  <transition name="fade-modal">
    <div class="backdrop-modal">
      <div class="modal"
        role="dialog"
        aria-labelledby="modalTitle"
        aria-describedby="modalDescription"
      >
        <header
          class="modal-header"
          id="modalTitle"
        >
          <slot name="header">
            This is the default tile!
          </slot>
          <button
            type="button"
            class="btn-close"
            @click="close"
            aria-label="Close modal"
          >
            x
          </button>
        </header>
 
        <section
          class="modal-body"
          id="modalDescription"
        >
          <slot name="body">
            Default Body.
          </slot>
        </section>
 
        <footer class="modal-footer">
          <slot name="footer">
            This is the default footer!
          </slot>
          <button
            type="button"
            class="green-btn"
            @click="close"
            aria-label="Close modal"
          >
            Close
          </button>
        </footer>
      </div>
    </div>
  </transition>
</template>
 
<style>
  .backdrop-modal {
    position: fixed;
    top: 0;
 
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
  }
 
  .modal {
    background: #FFFFFF;
    box-shadow: 3px 3px 20px 2px;
    overflow-x: auto;
    display: flex;
    flex-direction: column;
  }
 
  .modal-header,
  .modal-footer {
    padding: 20px;
    display: flex;
  }
 
  .modal-header {
    position: relative;
    border-bottom: 1px solid #eeeeee;
    color: #4AAEAC;
    justify-content: space-between;
  }
 
  .modal-footer {
    border-top: 1px solid #eeeeee;
    flex-direction: column;
  }
 
  .modal-body {
    position: relative;
    padding: 20px 10px;
  }
 
  .btn-close {
    position: absolute;
    border: none;
    top: 0;
    right: 0;
 
    font-size: 22px;
    padding: 11px;
    cursor: pointer;
    font-weight: bold;
    color: #4AAEAC;
    background: transparent;
  }
 
  .green-btn {
    color: white;
    background: #4AAEAC;
    border: 1px solid #4AAEAC;
    border-radius: 3px;
  }
 
  .fade-modal-enter,
  .fade-modal-leave-to {
    opacity: 0;
  }
 
  .fade-modal-enter-active,
  .fade-modal-leave-active {
    transition: opacity .5s ease;
  }
</style>

Copy

This is the foundation for an approachable and morphing modal subcomponent.

2. Conclusion

In this tutorial, you learned how to use Vue.js to create a modal component. To make your component more modular, you played around with slots; to enhance the usability of your component, you tried out transitions; and to make it easier to access, you used ARIA characteristics.

profile-image
Itesh Sharma

Itesh Sharma is core member of Sales Department at TatvaSoft. He has got more than 6 years of experience in handling the task related to Customer Management and Project Management. Apart from his profession he also has keen interest in sharing the insight on different methodologies of software development.

Comments

  • Leave a message...