Created
July 30, 2023 16:22
-
-
Save sayandedotcom/cfd39848edd55a2955b2a5efea99dc8e to your computer and use it in GitHub Desktop.
React Select Library with shadcnui's design systems and forms !
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Select Component --------------------------------------------------------------------------------- | |
"use client"; | |
import clsx from "clsx"; | |
import { ChevronDownIcon, X } from "lucide-react"; | |
import Select, { | |
ClearIndicatorProps, | |
DropdownIndicatorProps, | |
MultiValueRemoveProps, | |
components, | |
} from "react-select"; | |
import makeAnimated from "react-select/animated"; | |
import CreatableSelect from "react-select/creatable"; | |
const DropdownIndicator = (props: DropdownIndicatorProps) => { | |
return ( | |
<components.DropdownIndicator {...props}> | |
<ChevronDownIcon /> | |
</components.DropdownIndicator> | |
); | |
}; | |
const ClearIndicator = (props: ClearIndicatorProps) => { | |
return ( | |
<components.ClearIndicator {...props}> | |
<X /> | |
</components.ClearIndicator> | |
); | |
}; | |
const MultiValueRemove = (props: MultiValueRemoveProps) => { | |
return ( | |
<components.MultiValueRemove {...props}> | |
<X /> | |
</components.MultiValueRemove> | |
); | |
}; | |
const controlStyles = { | |
base: "border border-border rounded-lg bg-background hover:cursor-pointer hover:bg-secondary", | |
focus: "border-border ring-ring ring-primary-500", | |
nonFocus: "border-border", | |
}; | |
const placeholderStyles = "text-muted-foreground text-sm ml-1"; | |
const selectInputStyles = "text-foreground text-sm ml-1"; | |
const valueContainerStyles = "text-foreground text-sm"; | |
const singleValueStyles = "ml-1"; | |
const multiValueStyles = | |
"ml-1 bg-background border border-border rounded items-center py-0.5 pl-2 pr-1 gap-1.5"; | |
const multiValueLabelStyles = "leading-6 py-0.5"; | |
const multiValueRemoveStyles = | |
"border border-gray-200 bg-white hover:bg-red-50 hover:text-red-800 text-gray-500 hover:border-red-300 rounded-md bg-background"; | |
const indicatorsContainerStyles = "p-1 gap-1 bg-background rounded-lg"; | |
const clearIndicatorStyles = "text-gray-500 p-1 rounded-md hover:text-red-800"; | |
const indicatorSeparatorStyles = "bg-mutated"; | |
const dropdownIndicatorStyles = "p-1 hover:text-foreground text-gray-500"; | |
const menuStyles = "mt-2 p-2 border border-border bg-background text-sm rounded-lg"; | |
const optionsStyle = "bg-background p-2 border-0 text-base hover:bg-secondary hover:cursor-pointer"; | |
const groupHeadingStyles = "ml-3 mt-2 mb-1 text-gray-500 text-sm bg-background"; | |
const noOptionsMessageStyles = "text-muted-foreground bg-background"; | |
type SelectComponentProps = { | |
options: any[]; | |
value?: any; | |
onChange?: (value: any) => void; | |
isMulti?: boolean; | |
isDisabled?: boolean; | |
isLoading?: boolean; | |
createAble: boolean; | |
placeholder?: string; | |
}; | |
export const SelectComponent = ({ | |
options, | |
value, | |
onChange, | |
isMulti, | |
isDisabled, | |
isLoading, | |
createAble, | |
placeholder, | |
...props | |
}: SelectComponentProps) => { | |
const animatedComponents = makeAnimated(); | |
const Comp = createAble ? CreatableSelect : Select; | |
return ( | |
<> | |
<Comp | |
unstyled | |
isClearable | |
isSearchable | |
value={value} | |
isDisabled={isDisabled} | |
isMulti={isMulti} | |
isLoading={isLoading} | |
placeholder={placeholder} | |
components={animatedComponents} | |
// defaultInputValue={defaultValue} | |
defaultValue={value} | |
options={options} | |
noOptionsMessage={() => "No options found !!"} | |
onChange={onChange} | |
classNames={{ | |
control: ({ isFocused }) => | |
clsx(isFocused ? controlStyles.focus : controlStyles.nonFocus, controlStyles.base), | |
placeholder: () => placeholderStyles, | |
input: () => selectInputStyles, | |
option: () => optionsStyle, | |
menu: () => menuStyles, | |
valueContainer: () => valueContainerStyles, | |
singleValue: () => singleValueStyles, | |
multiValue: () => multiValueStyles, | |
multiValueLabel: () => multiValueLabelStyles, | |
multiValueRemove: () => multiValueRemoveStyles, | |
indicatorsContainer: () => indicatorsContainerStyles, | |
clearIndicator: () => clearIndicatorStyles, | |
indicatorSeparator: () => indicatorSeparatorStyles, | |
dropdownIndicator: () => dropdownIndicatorStyles, | |
groupHeading: () => groupHeadingStyles, | |
noOptionsMessage: () => noOptionsMessageStyles, | |
}} | |
{...props} | |
/> | |
</> | |
); | |
}; | |
2. Single Select Component with form --------------------------------------------------------------------------------- | |
const jobTypeList = [ | |
{ value: "Full Time", label: "Full Time" }, | |
{ value: "Part Time", label: "Part Time" }, | |
{ value: "Intern", label: "Intern" }, | |
{ value: "Temporary", label: "Temporary" }, | |
{ value: "Contractor", label: "Contractor" }, | |
{ value: "Volunteer", label: "Volunteer" }, | |
{ value: "Freelance", label: "Freelance" }, | |
]; | |
<FormField | |
control={form.control} | |
name="jobType" | |
render={({ field }) => ( | |
<FormItem> | |
<FormLabel>Joy Type</FormLabel> | |
<FormDescription>Select the job type.</FormDescription> | |
<SelectComponent | |
createAble={true} | |
isMulti={false} | |
value={field.value} | |
options={jobTypeList} | |
onChange={field.onChange} | |
placeholder="Select Job Type" | |
{...field} | |
/> | |
<FormMessage /> | |
</FormItem> | |
)} | |
/> | |
3. Multi Select Component with form --------------------------------------------------------------------------------- | |
const jobTypeList = [ | |
{ value: "Full Time", label: "Full Time" }, | |
{ value: "Part Time", label: "Part Time" }, | |
{ value: "Intern", label: "Intern" }, | |
{ value: "Temporary", label: "Temporary" }, | |
{ value: "Contractor", label: "Contractor" }, | |
{ value: "Volunteer", label: "Volunteer" }, | |
{ value: "Freelance", label: "Freelance" }, | |
]; | |
<FormField | |
control={form.control} | |
name="skills" | |
render={({ field }) => ( | |
<FormItem> | |
<FormLabel>Skills</FormLabel> | |
<FormDescription>Select the Skills Required.</FormDescription> | |
<SelectComponent | |
createAble={true} | |
isMulti={true} | |
value={field.value} | |
options={jobTypeList} | |
onChange={field.onChange} | |
placeholder="Select Skills" | |
{...field} | |
/> | |
<FormMessage /> | |
</FormItem> | |
)} | |
/> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
could u make passable for choosing element by arrow ?