custom_ui/frontend/src/components/SidebarSpeedDial.vue

80 lines
1.5 KiB
Vue

<script setup>
import { ref, watch } from "vue";
const props = defineProps({
icon: {
type: [Object, Function],
required: true,
},
label: {
type: String,
required: true,
},
items: {
type: Array,
default: () => [],
},
initiallyOpen: {
type: Boolean,
default: false,
},
forceOpen: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["opened", "closed"]);
const isOpen = ref(props.initiallyOpen);
const toggle = () => {
isOpen.value = !isOpen.value;
};
const handleItem = (item) => {
if (typeof item?.command === "function") {
item.command();
}
};
watch(
() => props.forceOpen,
(value) => {
if (value) {
isOpen.value = true;
}
},
);
watch(isOpen, (value) => {
if (value) {
emit("opened", props.label);
} else {
emit("closed", props.label);
}
});
</script>
<template>
<div class="sidebar-speeddial" :class="{ open: isOpen }">
<button class="sidebar-button" @click="toggle" :aria-expanded="isOpen">
<component :is="icon" class="button-icon" />
<span class="button-text">{{ label }}</span>
<span class="speeddial-caret" aria-hidden="true">{{ isOpen ? "-" : "+" }}</span>
</button>
<transition name="sidebar-accordion">
<div v-show="isOpen" class="sidebar-submenu">
<button
v-for="item in items"
:key="item.label"
class="sidebar-sub-button"
@click="handleItem(item)"
>
<span class="sub-button-text">{{ item.label }}</span>
</button>
</div>
</transition>
</div>
</template>