Files
web-temp/layers/components/atoms/Select.vue
2026-01-16 14:55:02 +09:00

100 lines
3.1 KiB
Vue

<script setup lang="ts">
interface Props {
options: Array<any>
labelName: string | number
modelValue?: object
placeholder?: string
defaultLabel?: string
placement?: string | 'top' | 'bottom'
className?: string
selectedColor?: string
}
const props = withDefaults(defineProps<Props>(), {
modelValue: null,
placeholder: null,
defaultLabel: null,
placement: 'bottom',
className: '',
selectedColor: '#333333',
})
const emits = defineEmits(['update:modelValue'])
const isActive = ref(false)
const isSelected = ref(props.defaultLabel !== null)
const selectedOption = ref<string>(props.placeholder || props.defaultLabel)
const onToggleOpen = () => {
isActive.value = !isActive.value
}
const onSelectOption = (option: { [key: string | number]: any }): void => {
isActive.value = false
isSelected.value = true
selectedOption.value = option[props.labelName]
emits('update:modelValue', option)
}
</script>
<template>
<div class="relative w-full max-w-[432px]">
<button
type="button"
class="relative flex items-center justify-between gap-[12px] w-full py-[12px] px-[16px] bg-white border-solid border-[1px] border-[#D9D9D9] rounded-[8px]"
@click="onToggleOpen"
>
<span
class="inline-flex items-center justify-left text-left text-[14px] font-[400] leading-[20px] tracking-[-0.42px]"
:class="isSelected ? 'text-[#333333]' : 'text-[#999999]'"
>
{{ selectedOption }}
</span>
<i
class="inline-flex items-center justify-center w-[14px] h-[14px] shrink-0"
>
<AtomsIconsSelectArrowDownFill
:size="12"
color="#333333"
:class="isActive ? 'rotate-180' : ''"
/>
</i>
</button>
<div
v-if="isActive"
:data-placement="props.placement"
class="absolute z-[10] top-full left-0 translate-y-[4px] w-full py-[8px] border-[1px] border-solid border-[rgba(0,0,0,0.3)] rounded-[8px] bg-white shadow-[0_4px_10px_0_rgba(0,0,0,0.10)]"
>
<ul class="relative flex flex-col items-center justify-start w-full">
<li
v-for="option in props.options"
:key="String(option[props.labelName])"
class="relative flex items-center justify-left w-full"
>
<button
type="button"
class="relative flex items-center justify-left w-full py-[8px] pl-[40px] pr-[16px] bg-white text-left text-[14px] font-[400] leading-[24px] tracking-[-0.42px] hover:bg-[rgba(0,0,0,0.04)]"
:class="
selectedColor ? `text-[${selectedColor}]` : 'text-[#333333]'
"
@click="onSelectOption(option)"
>
<template v-if="option[props.labelName] === selectedOption">
<i
class="absolute top-1/2 left-[12px] translate-y-[-50%] flex items-center justify-center w-[20px] h-[20px]"
>
<AtomsIconsCheckLine :size="16" :color="selectedColor" />
</i>
</template>
<span>
{{ option[props.labelName] }}
</span>
</button>
</li>
</ul>
</div>
</div>
</template>
<style scoped></style>