shade cn select field
Guest 178 14th Sep, 2026
import { useMemo } from "react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import FieldErrorMessage from "@/components/common/FieldErrorMessage"
import FormLabel from "@/components/common/FormLabel"
import { cn } from "@/lib/utils"
import type { FormSelectFieldProps } from "@/type/commonType"
import { getFormSelectFieldState } from "@/utils/formFieldValidation"
import { dedupeSelectOptions } from "@/utils/search"
export function FormSelectField({
label,
name,
value,
onChange,
options,
placeholder,
error,
touched,
isRequired = false,
className,
disabled = false,
isLoading = false,
loadingText = "Loading...",
noValueFoundText = "No options found",
valueType = "string",
}: FormSelectFieldProps) {
const uniqueOptions = useMemo(() => dedupeSelectOptions(options), [options])
const selectValue = value == null ? "" : String(value)
const handleValueChange = (val: string) => {
if (valueType === "number") {
;(onChange as (value: number) => void)(Number(val))
return
}
;(onChange as (value: string) => void)(val)
}
const fieldState = getFormSelectFieldState({
name,
touched,
error,
disabled,
isLoading,
})
return (
<div className={cn("mb-5 space-y-2", className)}>
<FormLabel
name={name}
label={label}
isRequired={isRequired}
className="text-micurato-steelGray"
/>
<Select
value={selectValue}
onValueChange={handleValueChange}
disabled={fieldState.isDisabled}
name={name}
>
<SelectTrigger
id={name}
className={cn("w-full", fieldState.hasError && "border-destructive")}
disabled={fieldState.isDisabled}
aria-invalid={fieldState.ariaInvalid}
aria-describedby={fieldState.ariaDescribedBy}
aria-busy={fieldState.isLoading || undefined}
>
<SelectValue
placeholder={fieldState.isLoading ? loadingText : placeholder}
/>
</SelectTrigger>
<SelectContent>
{fieldState.isLoading ? (
<p className="px-2 py-1.5 text-sm text-muted-foreground" role="status">
{loadingText}
</p>
) : uniqueOptions.length === 0 ? (
<p className="px-2 py-1.5 text-sm text-muted-foreground" role="status">
{noValueFoundText}
</p>
) : (
uniqueOptions.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))
)}
</SelectContent>
</Select>
<FieldErrorMessage
id={fieldState.errorId}
touched={touched}
errors={error}
className="min-h-[20px]"
/>
</div>
)
}
Description
No description
To share this paste please copy this url and send to your friends
RAW Paste Data