Source

components/shared/SmallHorizontalSelect.vue

<template lang="pug">
    .shs-wrapper(@click="e=>e.stopPropagation()")
        .shs-button(@click="handleButton")
            em(v-if="value.icon" :class="value.icon" :style="emStyle(value)")
            slot(:name="'icon_'+value.name" v-if="!value.icon"
                v-bind:item="value" v-bind:state="getItemState(value)" v-bind:vm="this"
            )
                span {{value.name||""}}
            em.fas.fa-caret-down(v-show="collapsed")
            em.fas.fa-caret-up(v-show="!collapsed")
        .shs-options(v-show="!collapsed")
            .shs-option(v-for="item in options" :key="item.name"
                @click="handleSelect(item)"
            )
              em(v-if="item.icon" :class="item.icon"
                v-b-tooltip.hover.bottom :title="item.label||item.title||item.name"
                :style="emStyle(item)"
              )
              slot(v-if="!item.icon" :name="'icon_'+item.name" v-bind:item="item" v-bind:state="getItemState(item)" v-bind:vm="this")
                span {{item.name.toUpperCase()}}
        slot
</template>
<script>
import colors from '@/styles/colors'

/**
 * Horizontal select that supports FontAwesome or Material icons (though slots)
 */
export default {
  props: {
    value: {
      type: Object,
      default: () => ({}),
    },
    options: {
      type: Array,
      default: () => [],
    },
    autoSelectFirst: {
      type: Boolean,
      default: true,
    },
    color: {
      type: String,
      default: colors.color_main,
    },
    size: {
      type: [Number, String],
      default: '20',
    },
  },
  data() {
    return {
      searchTypeHoverColor: '',
      collapsed: true,
    }
  },
  created() {
    if (this.autoSelectFirst) {
      this.$emit('input', this.options[0])
    }
  },
  mounted() {
    window.document.addEventListener(
      'click',
      (this.onclick = () => (this.collapsed = true))
    )
  },
  destroyed() {
    window.document.addEventListener('click', this.onclick)
  },
  methods: {
    getItemState(item) {
      return {
        size: this.getItemSize(item),
        color: this.getItemColor(item),
      }
    },
    getItemColor(item) {
      return item.color || this.color || 'black'
    },
    getItemSize(item) {
      let size = item.size || this.size
      if (!size.includes('px')) return parseInt(size)
      return size
    },
    emStyle(item) {
      let color = 'color:' + this.getItemColor(item) + ';'
      let size = this.getItemSize(item) ? `size:${this.getItemSize(item)}` : ''
      return `${color}${size}`
    },
    handleButton(e) {
      this.collapsed = !this.collapsed
      e.stopPropagation()
    },
    handleSelect(item) {
      this.$emit('input', item)
      this.collapsed = true
    },
  },
}
</script>
<style lang="scss">
.shs-wrapper {
  position: relative;
  z-index: 1000000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.shs-button {
  align-items: center;
  color: var(--color-dark-blue);
  display: flex;
  justify-content: center;
  cursor: pointer;
  column-gap: 5px;
}
.shs-options {
  position: absolute;
  left: 0px;
  top: -20px;
  display: flex;
  column-gap: 10px;
  padding: 5px 15px;
  box-shadow: 0px 2px 3px #0000005c;
  border-radius: 16px;
  background-color: white;
  width: fit-content;
  cursor: pointer;
}

.shs-option {
  em:hover {
    opacity: 0.9;
    cursor: pointer;
  }
}
</style>