In context
Workspace region picker, inline sort selector, role assignment with destructive tone option, and a grouped tech-stack picker with section labels and separators.
Workspace region
Single-value select with placeholder.
Inbox sort
Inline trigger paired with a filter chip row.
Assign role
Tone shifts to destructive on a role removal action.
Project tech stack
Grouped categories with separators.
Default
import { Select, SelectTrigger, SelectContent, SelectItem } from '@mihcm/ui/Select';
<Select value="apple" onValueChange={console.log}>
<SelectTrigger placeholder="Pick a fruit" />
<SelectContent>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="cherry">Cherry</SelectItem>
</SelectContent>
</Select>React Select searchable
import { ReactSelect, type DefaultReactSelectOption } from '@mihcm/ui/Select';
interface PeopleOption extends DefaultReactSelectOption {
meta: string;
}
<ReactSelect<PeopleOption>
options={groupedPeopleOptions}
defaultValue={groupedPeopleOptions[0].options[0]}
formatOptionLabel={(option) => (
<div className="flex min-w-0 items-center justify-between gap-3">
<span className="truncate font-medium">{option.label}</span>
<span className="shrink-0 text-xs text-muted-foreground">{option.meta}</span>
</div>
)}
placeholder="Search team or office..."
isSearchable
/>React Select multi with animation
import {
ReactSelect,
getReactSelectAnimatedComponents,
} from '@mihcm/ui/Select';
<ReactSelect
isMulti
closeMenuOnSelect={false}
components={getReactSelectAnimatedComponents()}
defaultValue={[peopleOptions[0], peopleOptions[2]]}
options={peopleOptions}
placeholder="Assign owners..."
/>React Select creatable
import { ReactCreatableSelect } from '@mihcm/ui/Select';
<ReactCreatableSelect
defaultValue={{ value: 'salary-review', label: 'Salary review' }}
options={[
{ value: 'salary-review', label: 'Salary review' },
{ value: 'onboarding', label: 'Onboarding' },
{ value: 'performance', label: 'Performance' },
]}
placeholder="Choose or create workflow..."
/>React Select async
import { ReactAsyncSelect } from '@mihcm/ui/Select';
const loadPeopleOptions = (inputValue: string) =>
fetch(`/api/people-options?q=${encodeURIComponent(inputValue)}`)
.then((response) => response.json());
<ReactAsyncSelect
cacheOptions
defaultOptions
loadOptions={loadPeopleOptions}
placeholder="Load people data..."
/>React Select async creatable
import { ReactAsyncCreatableSelect } from '@mihcm/ui/Select';
<ReactAsyncCreatableSelect
isMulti
cacheOptions
defaultOptions
loadOptions={loadPeopleOptions}
placeholder="Search or create tags..."
/>Popup select filter
Use this pattern for toolbar filters where the trigger summarizes the current selection and opens a searchable popup list. It follows the Atlassian popup-select behavior: a compact trigger, filtering inside the popup, multiple selection, rich option rows, and selected items kept visible.
Use this pattern for toolbar filters where the trigger summarizes the current selection.
import { ReactSelect, type DefaultReactSelectOption } from '@mihcm/ui/Select';
interface OwnerOption extends DefaultReactSelectOption {
description: string;
initials: string;
status: 'Available' | 'Busy' | 'Away';
}
function OwnerOptionLabel(option: OwnerOption) {
return (
<div className="flex min-w-0 items-center gap-3">
<span className="flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-xs font-semibold text-foreground">
{option.initials}
</span>
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-medium text-foreground">{option.label}</span>
<span className="block truncate text-xs text-muted-foreground">{option.description}</span>
</span>
<span className="shrink-0 rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground">
{option.status}
</span>
</div>
);
}
<ReactSelect<OwnerOption, true>
aria-label="Filter by owner"
isMulti
closeMenuOnSelect={false}
hideSelectedOptions={false}
controlShouldRenderValue={false}
value={selectedOwners}
onChange={setSelectedOwners}
options={ownerOptions}
formatOptionLabel={OwnerOptionLabel}
placeholder={selectedOwners.length > 0 ? `Owners: ${selectedOwners.length} selected` : 'Owner'}
classNames={{
control: ({ isFocused }) =>
cn(
'min-h-10 w-fit min-w-48 cursor-pointer rounded-md border bg-background px-2.5 text-body-sm shadow-sm',
'hover:bg-muted',
isFocused ? 'border-primary ring-2 ring-ring/20' : 'border-border',
),
placeholder: () => 'font-medium text-foreground',
}}
/>Sizes
<Select value="md" onValueChange={console.log}>
<SelectTrigger size="sm" placeholder="Small" />
<SelectContent>
<SelectItem value="sm">Small</SelectItem>
<SelectItem value="md">Medium</SelectItem>
</SelectContent>
</Select>
<Select value="md" onValueChange={console.log}>
<SelectTrigger size="lg" placeholder="Large" />
<SelectContent>
<SelectItem value="md">Medium</SelectItem>
<SelectItem value="lg">Large</SelectItem>
</SelectContent>
</Select>Destructive variant
<Select value="" onValueChange={console.log}>
<SelectTrigger variant="destructive" placeholder="Select action" />
<SelectContent>
<SelectItem value="delete">Delete account</SelectItem>
<SelectItem value="deactivate">Deactivate account</SelectItem>
</SelectContent>
</Select>With disabled items
<Select value="active" onValueChange={console.log}>
<SelectTrigger placeholder="Filter by status" />
<SelectContent>
<SelectItem value="active">Active</SelectItem>
<SelectItem value="pending">Pending</SelectItem>
<SelectItem value="archived" disabled>Archived</SelectItem>
</SelectContent>
</Select>With groups and separators
import {
Select, SelectTrigger, SelectContent,
SelectItem, SelectGroup, SelectLabel, SelectSeparator,
} from '@mihcm/ui/Select';
<Select value="fe" onValueChange={console.log}>
<SelectTrigger placeholder="Choose a role" />
<SelectContent>
<SelectGroup>
<SelectLabel>Engineering</SelectLabel>
<SelectItem value="fe">Frontend</SelectItem>
<SelectItem value="be">Backend</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Design</SelectLabel>
<SelectItem value="ux">UX Designer</SelectItem>
<SelectItem value="ui">UI Designer</SelectItem>
</SelectGroup>
</SelectContent>
</Select>