The MultiSelect component is a powerful and flexible React component built with TypeScript, Tailwind CSS, and shadcn/ui components. It provides advanced multi-selection functionality with extensive customization options.
- Multiple variants (default, secondary, destructive, inverted)
- Custom styling with badge colors and gradient backgrounds
- Grouped options with headings and separators
- Disabled options support
- Advanced animations (bounce, pulse, wiggle, fade, slide)
- Search and filter functionality
- Responsive design with mobile, tablet, and desktop configurations
- Form integration with React Hook Form and Zod validation
- Imperative methods via ref
- Accessibility support
options: Array of options or grouped optionsonValueChange: Callback function for value changesdefaultValue: Initial selected values (default: [])placeholder: Placeholder text (default: "Select options")
variant: "default" | "secondary" | "destructive" | "inverted"maxCount: Maximum badges to show (default: 3)autoSize: Auto width behavior (default: false)singleLine: Single line layout (default: false)
searchable: Enable search functionality (default: true)hideSelectAll: Hide select all button (default: false)closeOnSelect: Close popover after selection (default: false)disabled: Disable component (default: false)
responsive: Responsive configuration objectanimationConfig: Animation settings objectmodalPopover: Modal behavior (default: false)deduplicateOptions: Remove duplicate options (default: false)
interface AnimationConfig {
badgeAnimation?: "bounce" | "pulse" | "wiggle" | "fade" | "slide" | "none";
popoverAnimation?: "scale" | "slide" | "fade" | "flip" | "none";
optionHoverAnimation?: "highlight" | "scale" | "glow" | "none";
duration?: number;
delay?: number;
}interface MultiSelectOption {
label: string;
value: string;
icon?: React.ComponentType<{ className?: string }>;
disabled?: boolean;
style?: {
badgeColor?: string;
iconColor?: string;
gradient?: string;
};
}const [selectedValues, setSelectedValues] = useState<string[]>([]);
<MultiSelect
options={options}
onValueChange={setSelectedValues}
defaultValue={selectedValues}
placeholder="Select options"
/>;<FormField
control={form.control}
name="frameworks"
render={({ field }) => (
<FormItem>
<FormLabel>Frameworks</FormLabel>
<FormControl>
<MultiSelect
options={frameworksList}
onValueChange={field.onChange}
defaultValue={field.value}
placeholder="Select frameworks"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>const styledOptions = [
{
value: "web-app",
label: "Web Application",
icon: Icons.globe,
style: {
badgeColor: "#3b82f6",
gradient: "from-blue-500 to-purple-600",
},
},
];
<MultiSelect
options={styledOptions}
onValueChange={setValues}
animationConfig={{ badgeAnimation: "pulse" }}
variant="secondary"
/>;<MultiSelect
options={options}
onValueChange={setValues}
responsive={{
mobile: { maxCount: 1, compactMode: true },
tablet: { maxCount: 2, compactMode: false },
desktop: { maxCount: 4, compactMode: false },
}}
/>Perfect for selecting multiple AI models for comparison, A/B testing, or ensemble predictions.
Organize AI services by categories like Language Models, AI Agents, and Vector Databases.
Select different prompt template types with custom styling for various conversation patterns.
Choose multiple data sources for Retrieval-Augmented Generation systems.
Fine-tune AI model behavior by selecting generation and response control parameters.
Define agent capabilities across content creation, analysis, and communication.
Enable cross-modal capabilities like text-to-image, speech-to-text, etc.
const multiSelectRef = useRef<MultiSelectRef>(null);
// Reset to default values
multiSelectRef.current?.reset();
// Clear all selections
multiSelectRef.current?.clear();
// Focus the component
multiSelectRef.current?.focus();
// Get current values
const values = multiSelectRef.current?.getSelectedValues();
// Set specific values
multiSelectRef.current?.setSelectedValues(["react", "vue"]);Use with data visualization libraries for interactive filtering:
const [selectedDepartments, setSelectedDepartments] = useState<string[]>([]);
<MultiSelect
options={departmentOptions}
onValueChange={setSelectedDepartments}
placeholder="Filter departments"
/>;
// Use selectedDepartments to filter chart data
const filteredData = chartData.filter((item) =>
selectedDepartments.includes(item.department)
);- Use
animationConfigobject instead ofbadgeAnimationprop directly - Correct:
animationConfig={{ badgeAnimation: "pulse" }} - Incorrect:
badgeAnimation="pulse"
- Ensure
onValueChangeis connected to form field - Use proper default values to avoid controlled/uncontrolled warnings
- Handle empty arrays appropriately in validation schemas
- For large option lists, consider implementing virtualization
- Use
React.memofor option components if needed - Debounce search functionality for better UX
- Component includes proper ARIA labels and keyboard navigation
- Screen reader support is built-in
- Focus management is handled automatically
- Option Design: Use clear, descriptive labels and appropriate icons
- Grouping: Organize related options into logical groups
- Responsive: Configure appropriate maxCount for different screen sizes
- Validation: Implement proper form validation with clear error messages
- Performance: Use React.memo and useMemo for expensive operations
- Accessibility: Test with screen readers and keyboard navigation
- Animation: Use subtle animations that enhance UX without distraction
// Redux/Zustand
const selectedValues = useSelector((state) => state.multiSelect.values);
const dispatch = useDispatch();
<MultiSelect
options={options}
onValueChange={(values) => dispatch(setMultiSelectValues(values))}
defaultValue={selectedValues}
/>;// Next.js router
const router = useRouter();
const { values } = router.query;
<MultiSelect
options={options}
onValueChange={(newValues) => {
router.push({
pathname: router.pathname,
query: { ...router.query, values: newValues.join(",") },
});
}}
defaultValue={typeof values === "string" ? values.split(",") : []}
/>;