Multiple Choice
A multi-select field with customizable indicators, badge support, max selection limits, and a built-in 'none' option.
Demo
Preferred frameworks
Select all that apply
Installation
pnpm dlx shadcn@latest add @turbopills-ui/multiple-choicenpx shadcn@latest add @turbopills-ui/multiple-choiceyarn dlx shadcn@latest add @turbopills-ui/multiple-choicebunx shadcn@latest add @turbopills-ui/multiple-choiceUsage
tsx1import { MultipleChoice } from "@/components/turbopills/ui/multiple-choice"2import type { ChoiceOption } from "@/components/turbopills/ui/types"
tsx1const options: ChoiceOption[] = [2 { value: "email", label: "Email" },3 { value: "sms", label: "SMS" },4 { value: "push", label: "Push notifications" },5]67export function NotificationPreferences() {8 const [value, setValue] = React.useState<string[]>([])910 return (11 <MultipleChoice12 title="Notifications"13 hint="Select your preferred channels"14 options={options}15 value={value}16 onChange={setValue}17 />18 )19}
Examples
Max Selections
Limit the number of items a user can select with maxSelections. Options become disabled once the limit is reached:
Choose your plans
Select up to 2
None Option
An option with none: true acts as an exclusive toggle — selecting it deselects all other options, and selecting any other option deselects the "none" option:
Medical conditions
Select all that apply
Checkbox Variant
Use checkboxVariant="checkbox" for a traditional checkbox indicator instead of the default icon. Combine with checkboxPosition="left" to place the indicator before the label:
Notification preferences
Numbered Options
Enable showNumbers to display an index next to each option. Useful for ordered or ranked lists:
Rank your symptoms
Select the ones that apply
Props
MultipleChoiceProps
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Optional heading displayed above the options. |
hint | string | — | Optional hint text shown below the title. |
options | ChoiceOption[] | — | Required. Array of options to render. |
value | string[] | [] | Currently selected option values (controlled). |
onChange | (value: string[]) => void | — | Callback fired when the selection changes. |
maxSelections | number | — | Maximum number of items that can be selected. Remaining options become disabled once the limit is reached. |
disabled | boolean | false | Disables the entire field. |
checkboxPosition | "left" | "right" | "right" | Where to render the selection indicator relative to the label. |
checkboxVariant | "checkbox" | "icon" | "none" | "icon" | Visual style of the indicator. "icon" shows a filled circle-check, "checkbox" shows a standard checkbox, "none" hides the indicator. |
showNumbers | boolean | false | Displays a 1-based index badge next to each option. |
highlightOnHover | boolean | true | Applies a hover highlight to option rows. |
showOutlineOnSelect | boolean | true | Shows a border outline on selected options. |
showFillOnSelect | boolean | false | Fills the background of selected options. |
showShadowOnSelect | boolean | false | Adds a shadow to selected options. |
allowTextSelection | boolean | false | Allows selecting text inside option rows. Disabled by default to prevent accidental highlighting during repeated clicks. |
className | string | — | Additional class names for the root container. |
ChoiceOption
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. Unique identifier for the option. |
label | React.ReactNode | — | Required. Text or element displayed as the option label. |
badge | string | — | Optional badge text rendered next to the label. |
disabled | boolean | false | Disables this individual option. |
none | boolean | false | Marks this option as exclusive — selecting it deselects all others, and selecting any other deselects this one. |