63 lines
1.7 KiB
Vue
63 lines
1.7 KiB
Vue
|
<template>
|
||
|
<div v-click-outside="closeDropDown" :class="rootPT">
|
||
|
<button
|
||
|
id="dropdownDefaultButton"
|
||
|
data-dropdown-toggle="dropdown"
|
||
|
:class="titlePT"
|
||
|
type="button"
|
||
|
@click="
|
||
|
useRipple($event, props.ripple);
|
||
|
openMenu();
|
||
|
"
|
||
|
>
|
||
|
{{ props.title }}
|
||
|
<span :class="arrowPT">
|
||
|
<ml-arrow></ml-arrow>
|
||
|
</span>
|
||
|
</button>
|
||
|
<div v-show="isMenuOpen" :class="dropdownPT" @click="isOpen = false">
|
||
|
<slot />
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
<script setup lang="ts">
|
||
|
import { twMerge } from 'tailwind-merge';
|
||
|
import type { DropDownProps, DropDownPT } from './types';
|
||
|
|
||
|
const props = withDefaults(defineProps<DropDownProps>(), {
|
||
|
isOpen: false
|
||
|
});
|
||
|
|
||
|
const PT = {
|
||
|
root: {
|
||
|
class: 'relative pointer'
|
||
|
},
|
||
|
dropdown: {
|
||
|
class: 'z-10 absolute bg-white dark:bg-BgDark/85 rounded-3xl pointer text-black dark:text-white text-center'
|
||
|
},
|
||
|
title: {
|
||
|
class: 'text-black dark:text-BgLight inline-flex items-center rounded-lg font-medium text-center text-base pointer '
|
||
|
},
|
||
|
arrow: {
|
||
|
class: 'px-2'
|
||
|
}
|
||
|
} as DropDownPT;
|
||
|
|
||
|
const rootPT = computed(() => twMerge(PT.root?.class, props.pt?.root?.class));
|
||
|
const titlePT = computed(() => twMerge(PT.title?.class, props.pt?.title?.class));
|
||
|
const dropdownPT = computed(() => twMerge(PT.dropdown?.class, props.pt?.dropdown?.class));
|
||
|
const arrowPT = computed(() => twMerge(PT.arrow?.class, props.pt?.arrow?.class));
|
||
|
|
||
|
const isOpen = ref(props.isOpen);
|
||
|
|
||
|
function openMenu() {
|
||
|
isOpen.value = !isOpen.value;
|
||
|
}
|
||
|
|
||
|
function closeDropDown() {
|
||
|
isOpen.value = false;
|
||
|
}
|
||
|
|
||
|
const isMenuOpen = computed(() => isOpen.value);
|
||
|
</script>
|