Create Vue component for dropdowns and move it's styling to a separate .scss file while getting rid of the old, deprecated dropdowns in layout view
MODIFY
resources/assets/js/app.js
resources/assets/js/app.js
@@ -2,6 +2,7 @@ window.Vue = require('vue')
Vue.component('datepicker', require('./components/DatePicker.vue'))
Vue.component('barchart', require('./components/BarChart.vue'))
+Vue.component('dropdown', require('./components/Dropdown.vue'))
const app = new Vue({
el: '#app'

ADD
resources/assets/js/components/Dropdown.vue
+<template>
+ <div class="dropdown">
+ <button
+ ref="trigger"
+ class="dropdown__button"
+ @click="toggleModal">
+ <slot name="button"></slot>
+ </button>
+ <div
+ v-show="showModal"
+ class="dropdown__menu">
+ <slot name="menu"></slot>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ data() {
+ return {
+ showModal: false
+ }
+ },
+
+ methods: {
+ toggleModal() {
+ this.showModal = !this.showModal
+ },
+
+ closeModal() {
+ if (!this.belongsToUs(event.target)) {
+ this.showModal = false
+ }
+ },
+
+ belongsToUs(element) {
+ if (element == this.$refs.trigger) {
+ return true
+ }
+
+ if (this.$refs.trigger != undefined) {
+ const children = this.$refs.trigger.querySelectorAll('*')
+
+ for (const child of children) {
+ if (element == child) {
+ return true
+ }
+ }
+ }
+
+ return false
+ }
+ },
+
+ created() {
+ document.addEventListener('click', this.closeModal)
+ }
+}
+</script>

MODIFY
resources/assets/sass/app.scss
resources/assets/sass/app.scss
@import 'components/box';
@import 'components/input';
@import 'components/date-picker';
+@import 'components/dropdown';
@import 'components/helpers';
body {
@@ -25,32 +26,3 @@ body {
canvas {
width: 100%;
}
-
-.dropdown {
- position: relative;
-}
-
-ul.dropdown__list {
- position: absolute;
- top: 60px;
- right: 16px;
- padding: 10px 0;
- display: none;
- flex-direction: column;
- min-width: 140px;
- list-style: none;
- background: #FFF;
- box-shadow: 0 0 10px rgba(0, 0, 0, .1);
- border-radius: 5px;
-
- li a {
- padding: 5px 10px;
- display: block;
- white-space: nowrap;
-
- &:hover {
- color: #FFF;
- background: $colors-primary;
- }
- }
-}

ADD
resources/assets/sass/components/dropdown.scss
+.dropdown {
+ position: relative;
+
+ .dropdown__button {
+ font: inherit;
+ background: none;
+ color: inherit;
+ border: none;
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ &:focus {
+ outline: 0;
+ }
+ }
+
+ .dropdown__menu {
+ position: absolute;
+ top: 40px;
+ right: 0;
+ padding: 10px 0;
+ min-width: 150px;
+ border-radius: 5px;
+
+ ul {
+ list-style: none;
+
+ li a {
+ padding: 5px 10px;
+ display: block;
+ white-space: nowrap;
+
+ &:hover {
+ color: #FFF;
+ background: $colors-primary;
+ }
+ }
+ }
+ }
+}
+
+.theme-light .dropdown .dropdown__menu {
+ background: $colors-light-background;
+ border: 1px solid $colors-light-border;
+}
+
+.theme-dark .dropdown .dropdown__menu {
+ background: $colors-dark-background;
+ border: 1px solid $colors-dark-border;
+}

MODIFY
resources/views/layout.blade.php
resources/views/layout.blade.php
</li>
</ul>
<ul class="navigation__menu">
- <li class="dropdown">
- <a href="#" class="dropdown__toggle">
+ <li>
+ <dropdown>
+ <span slot="button">
<i class="far fa-plus mr-05"></i> <i class="fas fa-caret-down fa-sm"></i>
- </a>
- <ul class="dropdown__list">
+ </span>
+ <ul slot="menu">
<li>
<a href="/earnings/create">New earning</a>
</li>
<a href="/spendings/create">New spending</a>
</li>
</ul>
+ </dropdown>
</li>
@if (Auth::user()->spaces->count() > 1)
- <li class="dropdown">
- <a href="#" class="dropdown__toggle">
+ <li>
+ <dropdown>
+ <span slot="button">
{{ str_limit(session('space')->name, 3) }} <i class="fas fa-caret-down fa-sm"></i>
- </a>
- <ul class="dropdown__list">
+ </span>
+ <ul slot="menu">
@foreach (Auth::user()->spaces as $space)
<li>
<a href="/spaces/{{ $space->id }}">{{ $space->name }}</a>
</li>
@endforeach
</ul>
+ </dropdown>
</li>
@endif
- <li class="dropdown">
- <a href="#" class="dropdown__toggle">
+ <li>
+ <dropdown>
+ <span slot="button">
<img src="{{ Auth::user()->avatar ? '/storage/avatars/' . Auth::user()->avatar : 'http://placehold.it/50x50' }}" class="avatar mr-05" /> <i class="fas fa-caret-down fa-sm"></i>
- </a>
- <ul class="dropdown__list">
+ </span>
+ <ul slot="menu">
<li>
<a href="/settings">Settings</a>
</li>
<a href="/logout">Log out</a>
</li>
</ul>
+ </dropdown>
</li>
</ul>
</div>
</div>
<script src="/js/app.js"></script>
@yield('scripts')
- <script>
- var dropdowns = document.querySelectorAll('.dropdown__toggle');
-
- for (var i = 0; i < dropdowns.length; i ++) {
- var a = dropdowns[i];
-
- trigger(a);
- }
-
- function trigger(el) {
- el.addEventListener('click', function (e) {
- e.preventDefault();
-
- closeAll(el);
-
- var parent = e.target.parentNode;
-
- if (parent.nodeName != 'LI') {
- parent = parent.parentNode;
- }
-
- var x = parent.querySelector('.dropdown__list');
-
- if (x.style.display == 'flex') {
- x.style.display = 'none';
- } else {
- x.style.display = 'flex';
- }
- });
- }
-
- function closeAll(skip) {
- for (var i = 0; i < dropdowns.length; i ++) {
- if (dropdowns[i] != skip) {
- dropdowns[i].parentNode.querySelector('.dropdown__list').style.display = 'none';
- }
- }
- }
- </script>
</body>
</html>

Create Vue component for dropdowns and move it's styling to a separate .scss file while getting rid of the old, deprecated dropdowns in layout view