74 lines
4.2 KiB
Vue
74 lines
4.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed, defineProps } from 'vue'
|
|
import type { MenuItemModel } from '@/utils/interfaces'
|
|
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'
|
|
import { useMenuStore } from '@/stores/menu'
|
|
import { DotOutline } from '@/utils/icons'
|
|
import AsideMenuSingle from '@/components/Navigation/Aside/AsideMenuSingle.vue'
|
|
const menu = useMenuStore()
|
|
|
|
const props = defineProps({
|
|
item: {
|
|
type: Object as () => MenuItemModel,
|
|
required: true
|
|
},
|
|
selected: {
|
|
type: Boolean,
|
|
required: true
|
|
},
|
|
isChildren: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const isMenu = (name: string) => {
|
|
return menu.menuSelected === name
|
|
}
|
|
|
|
const isMenuSelected = computed(() => {
|
|
return props.item.children.find((d) => d.href === menu.menuSelected) || props.item.children.find((d) => d.children.find((e) => e.href === menu.menuSelected))
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div :class="[isChildren ? 'ml-2 mt-1 bg-primary-100 rounded-xl' : '']">
|
|
<Disclosure v-bind:default-open="isMenuSelected ? true : false" as="dev">
|
|
<!-- Nested item with children -->
|
|
<DisclosureButton @click="menu.toggleSidebarMenu(item.href, !item.expanded)"
|
|
:class="[(isMenuSelected || item.expanded || isChildren || item.expanded) ? 'bg-primary-100 text-primary-500 font-bold' : 'text-gray-600 font-semibold text-aside hover:bg-primary-100 hover:text-primary-500', isChildren ? 'pl-1 pr-2' : 'px-2', 'group w-full flex items-center py-2 text-left text-xs rounded-lg focus:outline-none focus:ring-0']">
|
|
<embed :src="isChildren ? DotOutline : item.icon"
|
|
:class="[isMenuSelected ? 'fill-primary-500' : 'fill-gray-400 group-hover:fill-gray-500', isChildren ? '' : 'mr-2', 'flex-shrink-0 w-6 h-6']"
|
|
type="image/svg+xml" />
|
|
<span class="flex-1">{{ item.name }}</span>
|
|
|
|
<svg :class="[isMenuSelected ? 'text-primary-500' : 'text-gray-300 group-hover:text-gray-500', item.expanded ? 'rotate-180' : '', 'ml-3 flex-shrink-0 transform transition-colors duration-150 ease-in-out ']"
|
|
width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path
|
|
d="M4.44002 8.9399C4.72127 8.659 5.10252 8.50122 5.50002 8.50122C5.89752 8.50122 6.27877 8.659 6.56002 8.9399L12 14.3799L17.44 8.9399C17.7244 8.67494 18.1005 8.53069 18.4891 8.53755C18.8777 8.54441 19.2484 8.70183 19.5233 8.97666C19.7981 9.25148 19.9555 9.62225 19.9624 10.0109C19.9692 10.3995 19.825 10.7756 19.56 11.0599L13.06 17.5599C12.7788 17.8408 12.3975 17.9986 12 17.9986C11.6025 17.9986 11.2213 17.8408 10.94 17.5599L4.44002 11.0599C4.15912 10.7787 4.00134 10.3974 4.00134 9.9999C4.00134 9.6024 4.15912 9.22115 4.44002 8.9399Z"
|
|
:fill="isMenuSelected ? '#14A2BA' : '#647375'" />
|
|
</svg>
|
|
</DisclosureButton>
|
|
<transition enter-active-class="overflow-hidden transition-all duration-300"
|
|
enter-from-class="transform scale-95 max-h-0" enter-to-class="transform scale-100 max-h-[1000px]"
|
|
leave-active-class="overflow-hidden transition-all duration-300"
|
|
leave-from-class="transform scale-100 max-h-[1000px]" leave-to-class="transform scale-95 max-h-0">
|
|
<div v-show="item.expanded">
|
|
<DisclosurePanel :class="['bg-primary-100 rounded-xl ml-4', 'space-y-1']" static>
|
|
<!-- Nested children -->
|
|
<template v-for="(subItem, index) in item.children" :key="subItem.href">
|
|
<!-- Single-level child -->
|
|
<AsideMenuSingle v-if="subItem.children.length === 0" :item="subItem" :is-children="true"
|
|
:selected="isMenu(subItem.href)" />
|
|
<!-- Multiple-level child -->
|
|
<AsideMenuMultiple v-else :item="subItem" :selected="subItem.href === menu.menuSelected"
|
|
:is-children="true" />
|
|
</template>
|
|
</DisclosurePanel>
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</Disclosure>
|
|
</div>
|
|
</template> |