Tangible Design System · @tangible/ui 0.2.29 · Interactive version · Markdown

MultiSelect

import { MultiSelect, useMultiSelect } from '@tangible/ui';

Interactive docs and examples: MultiSelect in Storybook.

MultiSelect props

Prop Type Default Description
children React.ReactNode
aria-describedby? string ID of element(s) that describe this select.
aria-invalid? "false" | "true" | boolean Marks the control invalid. Lands on the trigger, which also wears tui-input-group — that is what lights the danger border. Injected automatically by Field.Control when the Field has an error.
aria-label? string Accessible name for the select.
aria-labelledby? string ID of element that labels this select.
aria-required? "false" | "true" | boolean Marks the control required. Injected automatically by Field.Control when the Field is required.
defaultOpen? boolean false Default open state for uncontrolled usage.
defaultValue? MultiSelectValue Default values for uncontrolled usage.
disabled? boolean false Whether the entire select is disabled.
display? "chips" | "count" 'count' Display mode for the trigger. 'count': Shows "N selected"; 'chips': Shows visual chips for selected items
id? string Optional trigger ID override. Useful for Field integration via htmlFor.
labels? MultiSelectLabels Override internal display and screen reader strings for i18n. All keys are optional — omitted keys use English defaults.
max? number Maximum number of selections allowed. When reached, unselected options become disabled.
maxChips? number 3 Maximum number of chips to show before "+N more" badge. Only applies when display='chips'.
onMaxReached? () => void Callback when max selections is reached.
onOpenChange? (open: boolean) => void Callback when open state changes.
onValueChange? (value: MultiSelectValue) => void Callback when selection changes.
open? boolean Controlled open state.
placeholder? string '' Placeholder text when no values are selected.
size? "lg" | "md" | "sm" 'md' Control size.
value? MultiSelectValue Controlled selected values.

MultiSelect.Trigger

Also exported as MultiSelectTrigger.

Prop Type Default Description
asChild? boolean false When true, merges props onto the child element instead of wrapping. Child must be a single React element that accepts ref and event handlers.
children? React.ReactNode
className? string Additional CSS class names.

MultiSelect.Content

Also exported as MultiSelectContent.

Prop Type Default Description
children React.ReactNode
className? string Additional CSS class names.

MultiSelect.Option

Also exported as MultiSelectOption.

Prop Type Default Description
children React.ReactNode
value OptionValue The value for this option. Required and must be unique. Can be string or number.
className? string Additional CSS class names.
disabled? boolean false Whether this option is disabled.
textValue? string Text value for typeahead and chip labels. Required when children is not a string. If children is a string, defaults to that.

MultiSelect.Group

Also exported as MultiSelectGroup.

Prop Type Default Description
children? ReactNode
className? string

MultiSelect.Label

Also exported as MultiSelectLabel.

Prop Type Default Description
children? ReactNode
className? string

Hooks

useMultiSelect

useMultiSelect(): MultiSelectActionsContextValue & MultiSelectStateContextValue

Combined hook for components that need both. Convenience for Trigger/Content that need everything.

Returns:

Member Type Description
disabled boolean
placeholder string
display "chips" | "count"
maxChips number
max number | undefined
size "lg" | "md" | "sm"
labels Required<MultiSelectLabels>
triggerId string
listboxId string
ariaLabel? string
ariaLabelledBy? string
ariaDescribedBy? string
ariaInvalid? "false" | "true" | boolean
ariaRequired? "false" | "true" | boolean
setOpen (open: boolean) => void
toggleOption (optionValue: OptionValue, textValue: string) => void
clearAll () => void
registerOption (option: RegisteredOption) => void
unregisterOption (value: OptionValue) => void
refs { reference: React.RefObject<ReferenceType | null>; floating: React.RefObject<HTMLElement | null>; setReference: (node: ReferenceType | null) => void; setFloating: (node: HTMLElement | null) => void; }
listRef MutableRefObject<(HTMLElement | null)[]>
getReferenceProps (userProps?: React.HTMLProps<Element>) => Record<string, unknown>
getFloatingProps (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>
getItemProps (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>
open boolean
value MultiSelectValue
maxReached boolean
isSelected (optionValue: OptionValue) => boolean
getSelectedOptions () => RegisteredOption[]
activeIndex number | null
highlightedValue OptionValue | null
orderedOptions RegisteredOption[]
floatingStyles CSSProperties
floatingContext FloatingContext

RegisteredOption (the option of registerOption):

Member Type Description
value OptionValue
ref RefObject<HTMLElement | null>
disabled boolean
textValue string

Examples

Other stories: Basic, Chips Display Mode, Chips with Overflow, Default Value, Numeric Values, Max Selections, Disabled, Disabled Options, Groups, With Icons, Controlled, In Modal, Keyboard Navigation, Long List, Form Example, Sizes, Controlled Open, Static (Inspect) (interactive page).

Component API tokens

Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.