Skip to content
Snippets Groups Projects
TreeItems.vue 3.84 KiB
Newer Older
<script setup lang="ts">
import { iconsSet } from '../../common/constants/icons';
import TriangleIcon from '../../icons/Mono/TriangleIcon.vue';
import type { ITIProps } from '../../common/interfaces/componentsProps';
import { convertThemeToColor } from '../../common/helpers/common';
defineProps<ITIProps>();
const emit = defineEmits(['toggleIsOpen', 'onClick']);
</script>

<template>
  <ul>
    <li
      v-for="item of items"
      :key="item.label"
      :class="[
        'item',
        {
          pl27: !item.children,
          openContent: state.find((itemState) => itemState.label === item.label && itemState.isOpen),
        },
      ]"
    >
      <article>
        <section
          :class="[
            'textContainer',
            {
              pointer: item.children,
            },
          ]"
          @click="emit('toggleIsOpen', item)"
        >
          <TriangleIcon
            v-if="item.children"
            :class="[
              'openButton',
              {
                openButtonOpened: state.find((itemState) => itemState.label === item.label && itemState.isOpen),
                ? convertThemeToColor(item.color!, item.darknessColor ?? '500')
            "
            size="17"
          />
          <a
            :href="item.link"
            :target="item.linkBlank ? '_blank' : '_self'"
            :class="[
              'label',
              {
                bold: item.textStyle === 'bold',
                italic: item.textStyle === 'italic',
                isDarkerOnHover: item.link,
            :style="`color: ${item.color ? convertThemeToColor(item.color, item.darknessColor ?? '500') : color}`"
            @click="
              () => {
                item.isLinkClicked = true;
                if (!item.link) {
                  $emit('toggleIsOpen', item);
                $emit('onClick', item);
            ><component
              :is="iconsSet[item.iconBefore]"
              v-if="item.iconBefore"
              :color="convertThemeToColor(item.iconColor ?? 'black', item.darknessIconColor ?? '500')"
              style="min-width: 17px"
              size="17" />
            <span>{{ item.label }}</span
            ><component
              :is="iconsSet[item.iconAfter]"
              v-if="item.iconAfter"
              :color="convertThemeToColor(item.iconColor ?? 'black', item.darknessIconColor ?? '500')"
        </section>
        <section class="children">
          <TreeItems
            :items="item.children ?? []"
            :state="state"
            :themeColor="themeColor"
            @toggleIsOpen="emit('toggleIsOpen', $event)"
          />
        </section>
      </article>
    </li>
  </ul>
</template>

<style scoped>
.item {
  width: 100%;
  transition: all 0.4s ease;
  background-color: v-bind(themeColor);
}
.label {
  position: relative;
  padding: 4px 5px;
  background-color: v-bind(themeColor);
  word-break: break-word;
  transition: filter 0.3s ease;
}
.openButton {
  margin-right: 10px;
  min-width: 17px;
  transition: transform 0.3s ease;
}
.openButtonOpened {
  transform: rotate(180deg);
}
.children {
  width: 100%;
  padding-left: 15px;
  display: grid;
  grid-template-rows: 0fr;
  transition:
    all 0.3s ease-in,
    grid-template-rows 0.3s ease-out;
}
.children > ul {
  overflow: hidden;
}
.openContent > article > .children {
  grid-template-rows: 1fr;
  opacity: 1;
}
.textContainer {
  position: relative;
  display: flex;
}
.pointer {
  cursor: pointer;
}
.pl27 {
  padding-left: 27px;
}
.isDarkerOnHover:hover {
  filter: brightness(80%);