Files
simrsx-fe/app/components/pub/custom-ui/form/select.vue
Khafid Prayoga 790c76be56 style(form/select): improve select component styling and focus state
- Add focus outline and ring styles to SelectTrigger
- Conditionally apply text color based on modelValue
- Simplify SelectItem template structure
2025-09-12 15:26:23 +07:00

83 lines
2.1 KiB
Vue

<script setup lang="ts">
import { SelectRoot } from 'radix-vue'
import {
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from '~/components/pub/ui/select'
import { cn } from '~/lib/utils'
interface Item {
value: string
label: string
code?: string
}
const props = defineProps<{
modelValue?: string
items: Item[]
placeholder?: string
label?: string
separator?: boolean
class?: string
}>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
// Sort items with selected item first, then alphabetically
const sortedItems = computed(() => {
const itemsWithSelection = props.items.map(item => ({
...item,
isSelected: item.value === props.modelValue,
}))
return itemsWithSelection.sort((a, b) => {
// Selected item always comes first
if (a.isSelected && !b.isSelected) return -1
if (!a.isSelected && b.isSelected) return 1
// If neither or both are selected, sort by label alphabetically
return a.label.localeCompare(b.label)
})
})
function onValueChange(value: string) {
emit('update:modelValue', value)
}
</script>
<template>
<SelectRoot :model-value="modelValue" @update:model-value="onValueChange">
<SelectTrigger :class="cn('w-full focus:outline-none focus:ring-1 focus:ring-black bg-white', props.class)">
<SelectValue :placeholder="placeholder || 'Pilih item'" :class="cn(
props.modelValue ? 'text-black' : 'text-muted-foreground',
)" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel v-if="label">
{{ label }}
</SelectLabel>
<SelectItem v-for="item in sortedItems" :key="item.value" :value="item.value" class="cursor-pointer">
<div class="flex items-center justify-between w-full">
<span>{{ item.label }}</span>
<span v-if="item.code" class="text-xs text-muted-foreground ml-2">
{{ item.code }}
</span>
</div>
</SelectItem>
<SelectSeparator v-if="separator" />
</SelectGroup>
</SelectContent>
</SelectRoot>
</template>