You need to sign in or sign up before continuing.
FilterTabs.vue 2.24 KB
<template>
  <view :class="['flex overflow-x-auto no-scrollbar space-x-[24rpx]', wrapperClass]">
    <view v-for="(item, index) in tabs" :key="getItemKey(item, index)"
      :class="[
        'px-[32rpx] py-[16rpx] rounded-full text-[28rpx] whitespace-nowrap transition-colors',
        tabClass,
        isActive(item, index) ? activeClassComputed : inactiveClassComputed
      ]"
      @tap="handleSelect(item, index)"
    >
      <slot name="label" :item="item" :index="index">
        {{ getItemLabel(item) }}
      </slot>
    </view>
  </view>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  tabs: {
    type: Array,
    default: () => []
  },
  modelValue: {
    type: [String, Number],
    default: 0
  },
  labelKey: {
    type: String,
    default: 'title'
  },
  valueKey: {
    type: String,
    default: ''
  },
  wrapperClass: {
    type: String,
    default: ''
  },
  tabClass: {
    type: String,
    default: ''
  },
  activeClass: {
    type: String,
    default: ''
  },
  inactiveClass: {
    type: String,
    default: ''
  }
})

const emit = defineEmits(['update:modelValue', 'change'])

const activeClassComputed = computed(() => {
  return props.activeClass || 'bg-[#2563EB] text-white'
})

const inactiveClassComputed = computed(() => {
  return props.inactiveClass || 'bg-[#F3F4F6] text-[#6B7280]'
})

const getItemLabel = (item) => {
  if (typeof item === 'string') return item
  return item?.[props.labelKey] ?? ''
}

const getItemValue = (item, index) => {
  if (typeof item !== 'object' || item === null) return index
  if (props.valueKey && item[props.valueKey] !== undefined) return item[props.valueKey]
  return index
}

const getItemKey = (item, index) => {
  const value = getItemValue(item, index)
  return value ?? index
}

const isActive = (item, index) => {
  return getItemValue(item, index) === props.modelValue
}

const handleSelect = (item, index) => {
  const value = getItemValue(item, index)
  if (value === props.modelValue) return
  emit('update:modelValue', value)
  emit('change', value)
}
</script>

<style lang="less" scoped>
:deep(.no-scrollbar::-webkit-scrollbar) {
  display: none;
  width: 0;
  height: 0;
}

:deep(.no-scrollbar) {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
</style>