rewrite to conform with latest Laravel dropdown element

This commit is contained in:
Brian 2022-09-01 12:48:53 -06:00
parent c5612ba108
commit 2120fc8c4d
Signed by: brian
GPG Key ID: DE1A5390A3B84CD8

View File

@ -1,110 +1,95 @@
<template> <script setup>
<transition leave-active-class="duration-200"> import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
<div class="relative">
<div class="hover:cursor-pointer" @click="show = !show">
<slot name="trigger">
<svg v-show="!show" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class=""><polyline points="6 9 12 15 18 9"></polyline></svg>
<svg v-show="show" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class=""><polyline points="6 9 12 15 18 9"></polyline></svg>
</slot>
</div>
<div v-show="show" class="fixed inset-0 z-40" @click="show = false"></div> const props = defineProps({
align: {
<transition enter-active-class="ease-out duration-300" type: String,
enter-from-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" default: 'right',
enter-to-class="opacity-100 translate-y-0 sm:scale-100"
leave-active-class="ease-in duration-200"
leave-from-class="opacity-100 translate-y-0 sm:scale-100"
leave-to-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div v-show="show" @click="show = false" class="flex flex-col absolute right-0 bg-white border border-gray-300 shadow-md w-max z-50">
<slot></slot>
</div>
</transition>
</div>
</transition>
</template>
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
props: {
maxWidth: {
type: String,
default: '2xl',
},
}, },
width: {
setup(props) { type: String,
let show = ref(false) default: '48',
return { show }
}, },
contentClasses: {
mounted() { type: Array,
document.addEventListener('keydown', this.closeOnEscape) default: () => ['py-1', 'bg-white'],
},
beforeDestroy() {
document.removeEventListener('keydown', this.closeOnEscape)
},
computed: {
maxWidthClass() {
return {
'sm': 'sm:max-w-sm',
'md': 'sm:max-w-md',
'lg': 'sm:max-w-lg',
'xl': 'sm:max-w-xl',
'2xl': 'sm:max-w-2xl',
}[this.maxWidth]
},
},
methods: {
closeOnEscape(event) {
if (event.key === 'Escape' && this.show) {
this.show = false
}
},
}, },
}) })
// variables
let open = ref(false)
// computed properties
const widthClass = computed(() => {
return {
'48': 'w-48',
'52': 'w-52',
'56': 'w-56',
'60': 'w-60',
'64': 'w-64',
'72': 'w-72',
'80': 'w-80',
'96': 'w-96',
}[props.width.toString()]
})
const alignmentClasses = computed(() => {
if (props.align === 'left') {
return 'origin-top-left left-0'
}
if (props.align === 'right') {
return 'origin-top-right right-0'
}
return 'origin-top'
})
// lifecycle hooks
onMounted(() => {
document.addEventListener('keydown', closeOnEscape)
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', closeOnEscape)
})
// methods
const closeOnEscape = (event) => {
if (open.value && event.key === 'Escape') {
open.value = false
}
}
</script> </script>
<style scoped> <template>
/*.rotate { animation: rotation 2s infinite linear; } <div class="relative">
<div @click="open = ! open">
<slot name="trigger"></slot>
</div>
@keyframes rotation { <!-- Full Screen Dropdown Overlay -->
from { transform: rotate(0deg); } <div v-show="open" class="fixed inset-0 z-40" @click="open = false"></div>
to { transform: rotate(359deg); }
}
.dropdown-menu { <transition
display: flex; enter-active-class="transition ease-out duration-200"
flex-direction: column; enter-from-class="transform opacity-0 scale-95"
position: absolute; enter-to-class="transform opacity-100 scale-100"
right: 0; leave-active-class="transition ease-in duration-75"
background-color: hsl(0, 0%, 100%); leave-from-class="transform opacity-100 scale-100"
border: 1px solid hsl(240, 4.9%, 83.9%); leave-to-class="transform opacity-0 scale-95"
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); >
width: max-content; <div
} v-show="open"
class="absolute z-50 mt-2 rounded-md shadow-lg"
.dropdown-link { :class="[widthClass, alignmentClasses]"
display: flex; style="display: none;"
padding: 1rem 0.5rem 1rem 0.5rem; @click="open = false"
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; >
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); <div class="rounded-md ring-1 ring-black ring-opacity-5" :class="contentClasses">
transition-duration: 150ms; <slot name="content"></slot>
} </div>
</div>
.dropdown-link:hover { </transition>
background-color: hsl(240, 4.8%, 95.9%); </div>
} </template>
.dropdown-link:focus {
background-color: hsl(240, 4.8%, 95.9%);
outline: 2px solid transparent;
outline-offset: 2px;
}*/
</style>