✨ Introducing Spectrum CLI – Your favorite UI blocks, now just one command away.

Multiple Selector

Fast, composable, fully-featured multiple selector for React.

Installation

1

Install the package

2

Paste this code into your project

3

If you found that you can't select options using mouse click.

Thanks to @njdowdy for the short-term workaround. This is related to Command component in shadcn-ui.

Adjusting the line 120 in shadcn's Command.tsx (which is CommandItem's className) to:

"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-[selected='true']:bg-accent aria-[selected='true']:text-accent-foreground data-[disabled='true']:pointer-events-none data-[disabled='true']:opacity-50",

4

Update import paths as needed

Usage

Disable Option

Disabled

Disable First Item selected

The first item selected is a default behavior by cmdk and there is no way to control it. You can learn more about the issue.

Here is a workaround solution: by adding a dummy item.

Controlled Component

Hide Clear All Button

Creatable Selector

Create option when there is no option matched.

The async search is debounced by default. The delay time is 500ms if you do not provide it.

You can provide delay to customize the time. The delay prop only works with onSearch.

The empty text will not trigger the search. On the other hand, if the search had been triggered, and user delete all the texts, it will not trigger the search again and keep the current options with empty text.

Only works with onSearch prop. Trigger search when onFocus.

For example, when user click on the input, it will trigger the search to get initial options.

The empty text will trigger the search.

If you combine the async search and creatable, you can create option when there is no option matched.

If you combine the async search and creatable and group, you can still create option when there is no option matched.

Sync search is for search locally without any request to the server. This will not show loading indicator even if you provide it. The rest props are the same as async search. i.e.: creatable, groupBy, delay.

Manually Controlled Options

If you want to controlled options yourself, you can provide options prop.

Otherwise, defaultOptions is a better choice.

Grouped

Grouping options by specific key of object

Maximum Selected Count

Following example is set to 3. The default of max selected is Number.MAX_SAFE_INTEGER

Maximum Text Length

Following example is set to 5.

Hide Placeholder When Selected

If you would like to work as a normal input that hide the placeholder when there are options selected.

Just set hidePlaceholderWhenSelected to true

Fixed Options

Provide fixed: true in your value

ref

CommandProps and CommandInputProps Customization

Form

Properties

PropertyTypeDefault
value
Option[]
[]
defaultOptions
Option[]
[]
options
Option[]
placeholder
string
hidePlaceholderWhenSelected
boolean
false
onChange
(options: Option[]) => void
disabled
boolean
false
delay
number
500
triggerSearchOnFocus
boolean
false
onSearch
(value: string) => Promise<Option[]>
onSearchSync
(value: string) => Option[]
creatable
boolean
false
groupBy
string
maxSelected
number
Number.MAX_SAFE_INTEGER
onMaxSelected
(maxLimit: number) => void
loadingIndicator
ReactNode
emptyIndicator
ReactNode
selectFirstItem
boolean
true
className
string
badgeClassName
string
ref
React.RefObject<MultipleSelectorRef>
commandProps
React.ComponentPropsWithoutRef<typeof Command>
inputProps
Omit<React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>,'value' | 'placeholder' | 'disabled' >
hideClearAllButton
boolean

Build Beautiful Interfaces Like
Spectrum UI for Your Product

I help companies ship fast, clean UIs that users love.