rewrite to conform with latest Laravel dropdown element
This commit is contained in:
parent
c5612ba108
commit
2120fc8c4d
@ -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>
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user