Building A Modal With Vue - Js and Tailwind CSS - Laravel News
Building A Modal With Vue - Js and Tailwind CSS - Laravel News
M AY 3 1 , 2 0 1 9 / J A S O N B E G G S
// resources/assets/js/components/CardModal.vue
<template>
<div>
The modal will go here.
</div>
</template>
<script>
export default {
//
}
</script>
// resources/js/app.js
Vue.component('card-modal', require('./components/CardModal.vue').defa
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1
Laravel News
<title>{{ config('app.name', 'Laravel') }}</title>
<card-modal></card-modal>
</div>
</body>
</html>
Right now, the text inside the modal will always show. Let’s
start by making the component accept a prop to show or hide
the contents.
<template>
<div v-if="showing">
The modal will go here.
</div>
</template>
<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
}
}
</script>
Laravel News
We’ll also need to add a data property to our Vue instance so we
can show or hide the modal from outside the CardModal
component. We’ll default the property to false so the modal
will be hidden when the page loads.
<div id="app">
<h1 class="font-bold text-2xl text-gray-900 ">Example Project</h1>
<p class="mb-6">This is just a example text for my tutorial.</p>
<button
class="bg-blue-600 text-white px-4 py-2 text-sm uppercase tracki
@click="exampleModalShowing = true"
>
Show Modal
</button>
<card-modal :showing="exampleModalShowing"></card-modal>
</div>
Next, let’s add some styling to the modal. We’ll need a card
surrounding the contents and a semi-transparent background
around the card. The background will also need to be position
fixed so it can take up the full screen without moving any of the
other contents on the page. Let’s start by adding the
Laravel News
background and centering the contents. For the transparent
background, we will need to add a semi-75 color to our
Tailwind configuration.
<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
>
The modal will go here.
</div>
</template>
module.exports = {
theme: {
extend: {
colors: {
'bg-semi-75': 'rgba(0, 0, 0, 0.75)'
}
}
}
};
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cente
>
<div class="w-full max-w-2xl bg-white shadow-lg rounded-lg p-8">
Laravel News
The modal will go here.
</div>
</div>
Now that we have the basic styling finished, let’s update the
component to use a slot so the content of the modal can be
configured where the component is used instead of inside the
component. This will make the component much more
reusable.
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cente
>
<div class="w-full max-w-2xl bg-white shadow-lg rounded-lg p-8">
<slot />
</div>
</div>
<card-modal :showing="exampleModalShowing">
<h2>Example modal</h2>
<p>This is example text passed through to the modal via a slot.</p
</card-modal>
Laravel News
<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded-l
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-4"
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</template>
<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
},
methods: {
close() {
this.$emit('close');
}
}
};
</script>
Laravel News
You’ll see that the close method emits a close event. We’ll
need to listen for the event outside the component and update
the exampleModalShowing property to false. In the welcome
view, we can listen for the event by adding a @close listener on
the <card-modal> tag.
Now when we click the “Show Modal” button, the modal should
appear. When we click the close button or the x inside the
modal, the modal should disappear.
I’d also like the modal to close when the background behind
theLaravel
card isNews
clicked. Using Vue.js, it’s pretty easy to add that
functionality. We can just add @click.self="close" to the
background div and Vue will handle the rest. The .self
modifier will make it so the listener is only triggered when the
background itself is clicked. Without that modifier, the modal
would close whenever anything inside the card is clicked as
well, which is not what we want.
<template>
<div
v-if="showing"
class="fixed inset-0 w-full h-screen flex items-center justify-cen
@click.self="close"
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded-l
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-4"
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</template>
Adding a transition
<template>
<Transition name="fade">
<div
v-if="showing"
Laravel News
class="fixed inset-0 w-full h-screen flex items-center justify-c
@click.self="close"
>
<div class="relative w-full max-w-2xl bg-white shadow-lg rounded
<button
aria-label="close"
class="absolute top-0 right-0 text-xl text-gray-500 my-2 mx-
@click.prevent="close"
>
×
</button>
<slot />
</div>
</div>
</Transition>
</template>
// script...
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: all 0.4s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
<script>
export default {
props: {
showing: {
required: true,
type: Boolean
}
},
watch: {
showing(value) {
if (value) {
return document.querySelector('body').classList.add('overflow-
}
document.querySelector('body').classList.remove('overflow-hidden
}
},
methods: {
close() {
this.$emit('close');
}
}
};
</script>
Conclusion
L A R AV E L N E W S PA R T N E R S
Laravel News
Laravel Jobs
So ware Developer
Remote
Blueprint Title Company
Newsletter
Join 31,000+ others and never miss out on new tips, tutorials, and more.
Laravel News
NEWS TUTO RI ALS PAC K AG E S BOOKS INTERVIEWS
TRAINING RESOURCES A P P L I C AT I O N S
© 2 0 1 2 - 2 0 2 0 L A R AV E L N E W S — B Y E R I C L . B A R N E S - A D I V I S I O N O F D O T D E V I N C .
D E S I G N & F R O N T- E N D C O D E B Y