Newer
Older
<script setup lang="ts">

Дмитрий Малюгин
committed
import { computed } from 'vue';
import type { IMDProps } from '@interfaces/componentsProps';
import { convert500ThemeToColor } from '@helpers/colors';
import PlusIcon from '@stories/icons/Mono/PlusIcon.vue';
const props = withDefaults(defineProps<IMDProps>(), {
theme: 'white',
size: 'medium',
direction: 'right',
});
const active = defineModel('active');
const themeColor = computed(() => convert500ThemeToColor(props.theme));
const textColor = computed(() => {
if (props.theme === 'white') return '#000000';
return '#ffffff';
});
const elementsSize = computed(() => {
switch (props.size) {
case 'small':
return 30;
case 'large':
return 55;
return 70;
}
});
const menuListStyles = computed(() => {
switch (props.direction) {
case 'left':

Дмитрий Малюгин
committed
return `flex-direction: row-reverse; transform: translateY(-${elementsSize.value / 2}px) ${active.value ? `translateX(calc(-100% - 10px))` : 'translateX(calc(-100% + 60px))'}`;
case 'up':
return `flex-direction: column-reverse; transform: translateY(-${active.value ? (0.5 + props.items.length) * elementsSize.value + 15 : 1.5 * elementsSize.value}px) translateX(calc(-50% + ${elementsSize.value / 2}px))`;
case 'down':
return `flex-direction: column; transform: translateY(${active.value ? 25 : -20}px) translateX(calc(-50% + ${elementsSize.value / 2}px))`;

Дмитрий Малюгин
committed
return `transform: translateY(-${elementsSize.value / 2}px) translateX(${active.value ? elementsSize.value + 10 : -20}px)`;

Дмитрий Малюгин
committed
// const circleStylesItems = computed(() => {
// if (props.direction !== 'circle') {
// return '';
// }
// const styles = [];
// let deg = 0;
// const itemsCount = props.items.length;
// const degToItem = Math.round(360 / itemsCount);
// for (let i = 0; i < itemsCount; i++) {
// styles.push(`transform: rotate(${deg}deg) rotate(${-deg}deg)`);
// deg += degToItem;
// }
// console.log(styles);
// return styles;
// });
const openLink = (url: string, isBlank: boolean | undefined) =>
window.open(url, isBlank ? '_blank' : '_self');
</script>
<template>
<section class="menuContainer">
<button
:style="`border: ${theme === 'white' ? '2px solid black' : ''}; background-color: ${themeColor ?? 'white'}; width: ${elementsSize}px; height: ${elementsSize}px; transform: ${active ? 'rotate(135deg)' : ''};`"
class="menuButton"
>
<slot name="buttonIcon" />
<PlusIcon v-if="!$slots.buttonIcon" :size="elementsSize - 10" :color="textColor" />
</button>
<ul
:class="[
'menuList',
{
menuListColumn: direction === 'up' || direction === 'down',
]"
:style="menuListStyles"
>
<li
v-for="(item, index) of items"
:key="item.label"
:style="`height: ${elementsSize}px; background-color: ${convert500ThemeToColor(item.theme ?? 'white')};

Дмитрий Малюгин
committed
color: ${!item.theme || item.theme === 'white' ? 'black' : 'white'}; border-color: ${!item.theme || item.theme === 'white' ? 'black' : 'white'};`"
class="menuElement"

Дмитрий Малюгин
committed
@click="
() => {
if (item.link) openLink(item.link, item.linkBlank);
if (item.onClick) item.onClick();
}
"
>
<slot :name="`${index + 1}IconBefore`" />
<p
style="padding: 5px"
:class="[
'',
{
bold: item.textStyle === 'bold',
italic: item.textStyle === 'italic',
},
]"
>
{{ item.label }}
</p>
<slot :name="`${index + 1}IconAfter`" />
</li>
</ul>
</section>
</template>
<style scoped>
.menuContainer {
position: relative;
}
.menuButton {
position: relative;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
transition: 0.2s ease-in-out;
}
.menuButton:hover {
filter: brightness(90%);
}
.menuButton:active {
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
filter: brightness(75%);
}
.menuList {
display: flex;
pointer-events: none;
gap: 10px;
position: absolute;
top: 50%;
left: 0;
opacity: 0;
transition: 0.2s ease-in-out;
}
.menuListOpened {
pointer-events: auto;
opacity: 1;
}
.menuElement {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
border: 1px solid white;
border-radius: 5px;
user-select: none;
cursor: pointer;
transition: 0.2s ease-in-out;
}
.menuElement:hover {
filter: brightness(90%);
}
.menuElement:active {
filter: brightness(75%);
}
</style>