@takashi145/react-multi-select-buttons
v0.1.2
Published
Button-based multi-select components for React.
Downloads
419
Readme
@takashi145/react-multi-select-buttons
Button-based multi-select components for React.
Installation
npm install @takashi145/react-multi-select-buttonsComponents
MultiSelectButtons
A generic multi-select component that works with any value type.
import { useState } from 'react'
import { MultiSelectButtons } from '@takashi145/react-multi-select-buttons'
import type { MultiSelectButtonItem } from '@takashi145/react-multi-select-buttons'
const items: MultiSelectButtonItem<string>[] = [
{ key: 'apple', label: 'Apple', value: 'apple' },
{ key: 'banana', label: 'Banana', value: 'banana' },
{ key: 'orange', label: 'Orange', value: 'orange' },
]
function App() {
const [selected, setSelected] = useState<MultiSelectButtonItem<string>[]>([])
return (
<MultiSelectButtons
items={items}
selectedItems={selected}
maxSelection={2}
onChange={setSelected}
/>
)
}Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| items | MultiSelectButtonItem<T>[] | Yes | List of selectable items |
| selectedItems | MultiSelectButtonItem<T>[] | Yes | Currently selected items |
| maxSelection | number | Yes | Maximum number of items that can be selected |
| onChange | (items: MultiSelectButtonItem<T>[]) => void | Yes | Called when selection changes |
| renderValue | (params: RenderValueParams<T>) => ReactNode | No | Custom button renderer |
| onSelectionLimitReached | (item: MultiSelectButtonItem<T>) => void | No | Called when user taps an unselected item but the limit is already reached |
| onDisabledClick | (item: MultiSelectButtonItem<T>) => void | No | Called when user taps a disabled item |
| className | string | No | Class name for the container element |
| style | CSSProperties | No | Inline style for the container element |
NumberMultiSelectButtons
A convenience component for selecting numbers within a range.
import { useState } from 'react'
import { NumberMultiSelectButtons } from '@takashi145/react-multi-select-buttons'
function App() {
const [selected, setSelected] = useState<number[]>([])
return (
<NumberMultiSelectButtons
min={1}
max={10}
selectedValues={selected}
maxSelection={3}
onChange={setSelected}
/>
)
}Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| min | number | Yes | Minimum value (inclusive) |
| max | number | Yes | Maximum value (inclusive) |
| step | number | No | Step between values (default: 1) |
| selectedValues | number[] | Yes | Currently selected values |
| maxSelection | number | Yes | Maximum number of values that can be selected |
| onChange | (values: number[]) => void | Yes | Called when selection changes |
| getValueLabel | (value: number, index: number) => string | No | Custom label for each value |
| isValueDisabled | (value: number, index: number) => boolean | No | Whether a value should be disabled |
| renderValue | (params: RenderValueParams<number>) => ReactNode | No | Custom button renderer |
| onSelectionLimitReached | (value: number) => void | No | Called when user taps an unselected value but the limit is already reached |
| onDisabledClick | (value: number) => void | No | Called when user taps a disabled value |
| className | string | No | Class name for the container element |
| style | CSSProperties | No | Inline style for the container element |
Types
MultiSelectButtonItem<T>
type MultiSelectButtonItem<T> = {
key: Key
label: string
value: T
disabled?: boolean
}RenderValueParams<T>
type RenderValueParams<T> = {
item: MultiSelectButtonItem<T>
value: T
isSelected: boolean
isDisabled: boolean
isInteractive: boolean
selectedOrder: number | null
onClick: () => void
}Custom Rendering
Use the renderValue prop to fully replace the default button appearance.
<MultiSelectButtons
items={items}
selectedItems={selected}
maxSelection={3}
onChange={setSelected}
renderValue={({ item, isSelected, isDisabled, onClick }) => (
<button
type="button"
onClick={onClick}
disabled={isDisabled}
style={{
width: '100%',
padding: '14px 16px',
borderRadius: 999,
border: `1px solid ${isSelected ? '#111827' : '#d1d5db'}`,
background: isSelected ? '#111827' : '#ffffff',
color: isSelected ? '#ffffff' : '#111827',
}}
>
{item.label}
</button>
)}
/>License
MIT
