Home

Awesome

vue-universal-modal

Universal modal plugin for Vue@3
<a href="https://hoiheart.github.io/vue-universal-modal/" target="_blank">Demo</a>

⚠️ This plugin does not support Vue@2

Table of Contents

Introduction

vue-universal-modal plugin is based on the <a href="https://v3.vuejs.org/guide/teleport.html#teleport" target="_blank">teleport</a>.
It is very light and simple, but it provides essential features for modal use in applications.
(Such as Add & Remove, Visible & Hidden, Transition, Auto bind keyboard and mouse to close, Support SSR, A11Y...)
Here is the <a href="https://hoiheart.github.io/vue-universal-modal/" target="_blank">Demo</a>

Features

Install plugin

npm install vue-universal-modal

Insert teleport element in your html

...
<div id="app"></div>
<!-- teleport target -->
<div id="modals"></div>
...

Because SSR cannot be implemented by dynamically creating and ref referencing teleport elements, teleport targets must be inserted into html first.

And install plugin in vue application

import 'vue-universal-modal/dist/index.css';

import VueUniversalModal from 'vue-universal-modal';

app.use(VueUniversalModal, {
  teleportTarget: '#modals',
});

Options

app.use(VueUniversalModal, {
  teleportTarget: '#my-modals',
  modalComponent: 'MyModal',
});
nametypedetaultdescription
teleportTarget (required)string<a href="https://v3.vuejs.org/api/built-in-components.html#teleport" target="_blank">Teleport target</a>
modalComponentstring'Modal'Global modal component name

Usage modal

Insert the component wrapped with the modal component. (Slot based)

<template>
  <p>
    <button @click="showModal">Show modal</button>
  </p>
  <!-- If the option changed modal component the name
  <MyModal>
  -->
  <Modal v-model="isShow" :close="closeModal">
    <div class="modal">
      <p>Hello</p>
      <button @click="closeModal">close</button>
    </div>
  </Modal>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    const isShow = ref(false);

    function showModal() {
      isShow.value = true;
    }

    function closeModal() {
      isShow.value = false;
    }

    return {
      isShow,
      showModal,
      closeModal,
    };
  },
});
</script>

<style scoped lang="scss">
.modal {
  width: 300px;
  padding: 30px;
  box-sizing: border-box;
  background-color: #fff;
  font-size: 20px;
  text-align: center;
}
</style>

v1.0.x -> v1.1.x change point

props

nametypedetaultdescription
closefunction() => {}Function to close a modal (apply when click dimmed)
disabledbooleanfalseHandle just visibility (as in v-show)
optionsobject{}

props.options

nametypedetaultdescription
transitionnumber | false300transition duration
closeClickDimmedbooleantrueCloses the modal when dimmed is clicked
closeKeyCodenumber | false27 (esc)Closes the modal when press key
styleModalContentobject{}Inject modal content style (<a href="https://github.com/hoiheart/vue-universal-modal/blob/main/src/Modal.vue" target="_blank">.vue-universal-modal-content</a>)

emit events

Supports emit properties for all <a href="https://v3.vuejs.org/guide/transitions-enterleave.html#javascript-hooks">transition events.</a>

<template>
  <p>
    <button @click="showModal">Show modal</button>
  </p>
  <Modal
    v-model="isShow"
    :close="closeModal"
    @before-enter="beforeEnter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @after-leave="afterLeave"
  >
    <div class="modal">
      <p>Hello</p>
      <button @click="closeModal">close</button>
    </div>
  </Modal>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    const isShow = ref(false);

    function showModal() {
      isShow.value = true;
    }

    function closeModal() {
      isShow.value = false;
    }

    function beforeEnter() {
      console.log('before enter');
    }

    function afterEnter() {
      console.log('after enter');
    }

    function beforeLeave() {
      console.log('before leave');
    }

    function afterLeave() {
      console.log('after leave');
    }

    return {
      isShow,
      showModal,
      closeModal,
      beforeEnter,
      afterEnter,
      beforeLeave,
      afterLeave,
    };
  },
});
</script>

Handle global CSS

You can change it directly to your own style by referring to the <a href="https://github.com/hoiheart/vue-universal-modal/blob/main/src/Modal.vue" target="_blank">source</a>

.vue-universal-modal {
  /* Change dimmed color */
  background-color: rgba(255, 255, 0, 0.3);
}
.vue-universal-modal-content {
  /* Align to top (flex-direction property value is set to column) */
  justify-content: flex-start;
}

Example