Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
February 12, 2022 03:23 pm GMT

Make Reusable and Animated Drop-down with Vue, Tailwind and Laravel

Hello everyone ,

There is no doubt that reusable components is one of the main keys that makes developers life easier. Not only it makes the code elegant and sexy , but also it can be used in multiple projects and with just few tweaks and Voil! You have another version of your component effortlessly. In this article, I'm going to help you creating Vue JS 3 drop-down component with composition API styled Tailwind CSS and imported in Laravel 9 project. Our component is going to be reusable, dynamic and animated as well.

Take a peak on what we will be creating :

I'm sure you can style it better than this, I just wanted to show you variety of options.

Another peak on the code :

<Dropdown title="Users Dropdown">  <Dropdowncontent>    @foreach ($users as $user)    <Dropdownitems item="{{ $user->name }}"                    href="/users/{{ $user->id }}">    </Dropdownitems>    @endforeach  </Dropdowncontent></Dropdown>

Before we start, please raise your hand if you have any questions:

You keep mentioning 'reusable', what does it mean?

  • A reusable component is a component that can be used in various parts of an application. For example, once we build our drop-down today you can use it in you web app as many times as you want without having to duplicates your code.

Why do you talk too much ?

  • Sorry, lets get to it.

1- Prerequisites:

  • I'm expecting that you have very basic knowledge of Vue composition API, Tailwind CSS and Laravel. If you don't, just come along for the ride and follow each step carefully.
  • I will build the reusable component from scratch continuing on using the same REPO that we created in the previous article.
  • If you would like to code along without my repo just make sure to install Laravel, Tailwind and Vue Js 3. Also create a database with users table or whatever and connect to it as we will be looping over the table. Instructions on how to do so is in PART 1.
  • Make sure you're running the command npm run watch all the time.

2- Allow Tailwind to read Vue files:

  • Head to tailwind.config.js and within the content array, be specific about your Vue files path.
module.exports = {  content: [    "./resources/**/*.blade.php",    "./resources/**/*.js",    "./resources/**/*.vue",    "./resources/js/components/*.vue",    "./resources/js/**/*.vue",  ],  theme: {    extend: {},  },  plugins: [],};
  • Insure npm run watch is running in the terminal.

3- Create a general Dropdown.vue component:

  • Head to resources/js/components and create new file called Dropdown.vue.
  • Within this file just build a normal drop-down component without looping over any data in database, just a toggle with showUsers function and some tailwind.

  • Dropdown.vue :

<template>  <div v-click-outside="onClickOutside" @click="showUsers">    <!-- toggler -->    <button      class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9              text-sm font-semibold lg:inline-flex lg:w-48">      Users    </button>    <!-- Content Container -->    <div v-show="usersToggle" class="mt-2 w-full rounded-lg bg-                                      blue-100 py-2">      <!-- Drop-down Items -->      <a href="#" class="block text-sm my-1 mx-1">            Random user name      </a>    </div>  </div></template>
<script>import vClickOutside from "click-outside-vue3";import { ref } from "vue";export default {    name: "Dropdown",    directives: {        clickOutside: vClickOutside.directive,    },    setup() {        const usersToggle = ref(false);        const showUsers = () => {            usersToggle.value = !usersToggle.value;        };        const onClickOutside = (event) => {            usersToggle.value = false;        };        return {            usersToggle,            showUsers,            onClickOutside,        };    },};</script>
  • Import your component in resources/js/app.js.
require("./bootstrap");import { createApp } from "vue";import Dropdown from "./components/Dropdown";import vClickOutside from "click-outside-vue3";createApp({  components: {    Dropdown,  },})  .use(vClickOutside)  .mount("#app");
  • Just a reminder that the vClickOutside is an npm package we used in the previous tutorial to close the drop-down when we click anywhere on the screen.

  • With nothing else, if you run the command php artisan serve in your Laravel's main directory you will see a functional ugly drop-down But don't worry, we will make it prettier later.

4- Create component parts:

Now we're going to slice our component as we need 3 parts. One for the toggler, one for the content container and one for the drop-down items. But first we must create and import them.

  • Head to resources/js/components/ and create the other two files Dropdowncontent.vue and Dropdownitems.vue.
  • Just make them contain <template> and <script> tags and leave them empty for now.
  • Import them in resources/js/app.js like we did with the first one.

  • resources/js/app.js :

import { createApp } from "vue";import Dropdown from "./components/Dropdown";import Dropdowncontent from "./components/Dropdowncontent";import Dropdownitems from "./components/Dropdownitems";import vClickOutside from "click-outside-vue3";createApp({  components: {    Dropdown,    Dropdowncontent,    Dropdownitems,  },})  .use(vClickOutside)  .mount("#app");

5- Slice Dropdown.vue:

  • Head to resources/js/components/Dropdown.vue and copy the div the contains the link and leave in it's place <slot /> tag and wrap the botton with <slot name="toggler"></slot> tags.
  • Head to resources/js/components/Dropdowncontent.vue and paste the div in the template. Then copy the link inside the div from Dropdowncontent.vue to Dropdownitems.vue and leave in it's place <slot /> tag as well.
  • Your components should look like this:

  • Dropdown.vue :

<template>  <div v-click-outside="onClickOutside" @click="showUsers">    <!-- toggler -->    <slot name="toggler">      <button        class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9                text-sm font-semibold lg:inline-flex lg:w-48">        Users      </button>    </slot>    <!-- Content Container -->    <slot />  </div></template>
  • Dropdowncontent.vue :
<template>  <div v-show="usersToggle" class="mt-1 w-full rounded-xl bg-blue-                                    100 py-2">    <slot />  </div></template>
<script>export default {    name: "Dropdowncontent",};</script>
  • Dropdownitems.vue :
<template>  <a href="#" class="block text-sm my-1 mx-1"> A user name </a></template>
<script>export default {    name: "Dropdownitems",};</script>
  • Head to welcome.blade.php and let's break it down in the body.

  • welcome.blade.php :

<!DOCTYPE html><html lang="en">  <head>    <title>dropdown</title>    <link href="{{ asset('css/app.css') }}" rel="stylesheet" />    <script src="{{ asset('js/app.js') }}" defer></script>  </head>  <body>    <main class="max-w-6xl mx-auto mt-6 lg:mt-20 space-y-6"           id="app">      <div class="max-w-xl mx-auto mt-10 text-center">        <div class="space-y-2 lg:space-y-0 lg:space-x-4 mt-8">          <div            class="relative lg:inline-flex items-center bg-blue-                    100 rounded-xl">            <Dropdown>              <Dropdowncontent>                <Dropdownitems></Dropdownitems>              </Dropdowncontent>            </Dropdown>          </div>        </div>      </div>    </main>  </body></html>
  • Now if you check it on browser, you will see the same thing but the toggler won't work. You might be wondering about how the heck are we going to pass usersToggle value from Dropdown.vue to Dropdowncontent.vue and really it's pretty simply, we're going to use Vue's provide/inject.

6- Provide/Inject:

  • Head to Dropdown.vue and import provide from vue, use it in the setup.

  • Dropdown.vue :

<script>import vClickOutside from "click-outside-vue3";import { provide, ref } from "vue";export default {    name: "Dropdown",    directives: {        clickOutside: vClickOutside.directive,    },    setup() {        const usersToggle = ref(false);        const showUsers = () => {            usersToggle.value = !usersToggle.value;        };        const onClickOutside = (event) => {            usersToggle.value = false;        };        provide("usersToggle", usersToggle);        return {            usersToggle,            showUsers,            onClickOutside,        };    },};</script>
  • Head to Dropdowncontent.vue and import inject, use it and return the value.

  • Dropdowncontent.vue :

<script>import { inject } from "vue";export default {    name: "Dropdowncontent",    setup() {        const usersToggle = inject("usersToggle");        return {            usersToggle,        };    },};</script>
  • And just like that, our drop-down is working again.

7- Pass the data from Blade to Vue:

  • To make this component more reusable and dynamic, let's head to Dropdown.vue and instead of hard coding the word 'Users' leave instead {{ title }} and accept title as a prop in the script.

  • Dropdown.vue :

<template>  <div v-click-outside="onClickOutside" @click="showUsers">    <!-- toggler -->    <button      class="flex max-h-52 w-full overflow-auto py-2 pl-3 pr-9              text-sm font-semibold lg:inline-flex lg:w-48">      {{ title }}    </button>    <!-- Content Container -->    <slot />  </div></template>
<script>import vClickOutside from "click-outside-vue3";import { provide, ref } from "vue";export default {    name: "Dropdown",    props: ["title"],    directives: {        clickOutside: vClickOutside.directive,    },    setup() {        const usersToggle = ref(false);        const showUsers = () => {            usersToggle.value = !usersToggle.value;        };        const onClickOutside = (event) => {            usersToggle.value = false;        };        provide("usersToggle", usersToggle);        return {            usersToggle,            showUsers,            onClickOutside,        };    },};</script>
  • Head to Dropdownitems.vue and do the same. Remove 'A user name' and leave instead {{ itemName }} and accept it as a prop.

  • Dropdownitems.vue :

<template>  <a href="#" class="block text-sm my-1 mx-1"> {{ item }} </a></template>
<script>export default {    name: "Dropdownitems",    props: ["item"],};</script>
  • Head to welcome.blade.php and pass on the values.

  • welcome.blade.php :

<Dropdown title="Users Dropdown">  <Dropdowncontent>    <Dropdownitems item="Testing Items" href="#" />  </Dropdowncontent></Dropdown>
  • Use @foreach loop to loop over all users in database and echo out their names.
<Dropdown title="Users Dropdown">  <Dropdowncontent>    @foreach ($users as $user)    <Dropdownitems item="{{ $user->name }}"                    href="/users/{{ $user->id }}">    </Dropdownitems>    @endforeach  </Dropdowncontent></Dropdown>

And there you go This is a complete dynamic and reusable drop-down component. You can even add to classes by passing them from blade just like we did with title, item name and href.

Dynamic dropdown component

8- Adding animation and styles:

  • You can get SVG website and add it to the button in Dropdown.vue.
  • I added a class conditionally for it to rotate when the usersToggle is true.
  • Also i made few changes to Tailwind CSS styles.

  • Dropdown.vue :

<template>  <div class="relative" v-click-outside="onClickOutside" @click="showUsers">    <slot name="toggler">      <button        class="text-white bg-gradient-to-r from-purple-600 to-                blue-500 rounded-xl flex max-h-52 w-full overflow-                auto py-2 pl-3 pr-9 text-sm font-semibold                lg:inline-flex lg:w-52">        {{ title }}        <svg          class="absolute"          :class="usersToggle? '-rotate-90 transform transition duration-500 ease-in-out': 'rotate-90 transform transition duration-500 ease-in-out'"          style="right: 12px"          width="22"          height="22"          viewBox="0 0 22 22">          <g fill="none" fill-rule="evenodd">            <path              stroke="#000"              stroke-opacity=".012"              stroke-width=".5"              d="M21 1v20.16H.84V1z"            ></path>            <path              fill="#222"              d="M13.854 7.224l-3.847 3.856 3.847 3.856-1.184 1.184-5.04-5.04 5.04-5.04z"            ></path>          </g>        </svg>      </button>    </slot>    <slot />  </div></template>
  • I used Vue's <transition> tags combined with tailwind CSS classes to make a smooth effect for the drop-down.

  • Dropdwoncontent.vue :

<template>  <transition    :duration="1000"    enter-active-class="transform transition duration-300 ease-     custom"    enter-class="-translate-y-1/2 scale-y-0 opacity-0"    enter-to-class="translate-y-0 scale-y-100 opacity-100"    leave-active-class="transform transition duration-300 ease-     custom"    leave-class="translate-y-0 scale-y-100 opacity-100"    leave-to-class="-translate-y-1/2 scale-y-0 opacity-0">    <div      v-show="usersToggle"      class="absolute left-0 right-0 z-50 mt-2 w-full rounded-lg              bg-gradient-to-r from-purple-600 to-blue-500 py-1 px-              3 text-left text-sm font-semibold text-white              transition duration-300 py-2">      <slot />    </div>  </transition></template>
  • Dropdownitems.vue :
<template>  <a    href=""    class="px-1 py-1 my-1 rounded-lg block hover:bg-gradient-to-bl            focus:bg-gradient-to-bl focus:ring-4 focus:ring-blue-            300 dark:focus:ring-blue-800">    <slot>{{ item }}</slot>  </a></template>

9- Extracting UsersDropdown blade component:

  • This is not necessary as the code still looks great but we can extract a blade component for it and.
  • Create new folder named components in resources/views and create inside it a new file named users-dropdown.blade.php.
  • Cut your drop-down code and paste it inside, leave in it's place <x-users-dropdown />.
  • That will leave us with only this code in our welcome.blade.php:
          <!-- Only this -->          <x-users-dropdown />

Congratulations Now you have a Vue animated, dynamic, reusable and colorful drop-down component inside a blade component with a very elegant code and cool Tailwind styles.

That's it for this tutorial and I hope you enjoyed reading it as I made huge effort due to the article being deleted and I had to rewrite it again. If you liked it please leave a reaction and if you have any questions leave it below or send me a DM on TWITTER directly.

Have a great day and happy coding


Original Link: https://dev.to/moose_said/make-reusable-and-animated-drop-down-with-vue-tailwind-and-laravel-4fp3

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To