Skip to main content

Select

Basic

Basic example of a select component. It uses a list of options to render a modal with a search input and a list of options.

Select destination...

const FlightDestinationComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$primary.500"].val,
color["$primary.300"].val
);

return (
<Select
includeSearch
estimatedItemSize={76}
modalTitle="Where to?"
modalSubtitle="Choose your dream destination"
placeholder="Select destination..."
options={destinations}
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Plane size={20} color={iconColor} />
</ListItem.Icon>
<HStack gap="$2" alignItems="center">
<VStack flex={1} gap="$0.5">
<ListItem.Title>{item.city}</ListItem.Title>
<ListItem.Subtitle>
{item.country}{item.flightTime}
</ListItem.Subtitle>
</VStack>
<Badge size="sm">{item.airport}</Badge>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => `${item.city} (${item.airport})`}
/>
);
};

Handle Submit Editing

This example demonstrates how to handle the onSubmitEditing event in the Select component. When the user submits their selection, the selected text is logged to the console. The appearance of the select component may change based on the color mode (light or dark).

Choose team member...

const TeamMemberComponent = () => {
const bgColor = useColorModeValue("white", "$primaryDark.0");
const onlineColor = useColorModeValue("$emerald.500", "$emerald.400");
const awayColor = useColorModeValue("$amber.500", "$amber.400");
const offlineColor = useColorModeValue("$primaryGray.400", "$primaryGray.500");

const getStatusColor = (status: TeamMember["status"]) => {
switch (status) {
case "online":
return onlineColor;
case "away":
return awayColor;
case "offline":
return offlineColor;
}
};

return (
<Select
includeSearch
estimatedItemSize={76}
modalTitle="Assign Task"
modalSubtitle="Select a team member to assign this task"
placeholder="Choose team member..."
onSubmitEditing={(e) => console.log(e.nativeEvent.text)}
options={teamMembers}
renderItem={({ item }) => (
<ListItem>
<HStack gap="$3" alignItems="center" flex={1}>
<Box position="relative">
<Avatar size="sm" source={{ uri: item.avatar }} />
<Box
position="absolute"
bottom={0}
right={0}
width={10}
height={10}
borderRadius="$12"
backgroundColor={getStatusColor(item.status)}
borderWidth={2}
borderColor={bgColor}
/>
</Box>
<VStack flex={1}>
<ListItem.Title>{item.name}</ListItem.Title>
<ListItem.Subtitle>{item.role}</ListItem.Subtitle>
</VStack>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.name}
/>
);
};

Disabled

Use the isDisabled prop to disable the Select component. When the component is disabled, users cannot interact with it.

Room booking unavailable...

const MeetingRoomDisabledComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$primaryGray.400"].val,
color["$primaryGray.500"].val
);

return (
<Select
isDisabled={true}
placeholder="Room booking unavailable..."
options={meetingRooms}
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Building2 size={20} color={iconColor} />
</ListItem.Icon>
<ListItem.Title>{item.name}</ListItem.Title>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.name}
/>
);
};

Use the includeSearch prop to disable the search input in the Select component. When the search input is disabled, users cannot search for options.

Select priority level...

const PriorityLevelComponent = () => {
return (
<Select
modalTitle="Set Priority"
modalSubtitle="How urgent is this task?"
includeSearch={false}
placeholder="Select priority level..."
options={priorityLevels}
renderItem={({ item }) => (
<ListItem>
<HStack gap="$3" alignItems="center" flex={1}>
<Box
width={12}
height={12}
borderRadius="$12"
backgroundColor={`$${item.colorToken}.500`}
/>
<VStack flex={1}>
<ListItem.Title>{item.label}</ListItem.Title>
<ListItem.Subtitle>{item.description}</ListItem.Subtitle>
</VStack>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.label}
/>
);
};

Search Changed Event Handling

This example illustrates how to handle the onSearchTermChanged event in the Select component. When the user searches for a term, the component filters the options list accordingly. You can customize this event handler to perform additional actions, such as making API calls.

All categories...

const JobCategoryComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$indigo.500"].val,
color["$indigo.300"].val
);

const onSearchTermChanged = (searchTerm: string) => {
return jobCategories.filter((item) =>
item.title.toLowerCase().includes(searchTerm.toLowerCase())
);
};

return (
<Select
modalTitle="Browse Jobs"
modalSubtitle="Filter by department"
onSearchTermChanged={onSearchTermChanged}
placeholder="All categories..."
options={jobCategories}
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Briefcase size={20} color={iconColor} />
</ListItem.Icon>
<HStack flex={1} justifyContent="space-between" alignItems="center">
<ListItem.Title>{item.title}</ListItem.Title>
<Badge
borderWidth={0}
size="sm"
_container={{ paddingVertical: "$0.5" }}
>
{item.openings} open
</Badge>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.title}
/>
);
};

Item Selected Event Handling

This example demonstrates how to handle the onItemSelected event in the Select component. When a user selects an item from the list, the selected item is logged to the console.

Choose time...

const RestaurantBookingComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$primary.500"].val,
color["$primary.400"].val
);
const availableColor = useColorModeValue("$emerald.600", "$emerald.400");
const limitedColor = useColorModeValue("$amber.600", "$amber.400");
const fullColor = useColorModeValue("$red.500", "$red.400");

const getAvailabilityColor = (availability: TimeSlot["availability"]) => {
switch (availability) {
case "available":
return availableColor;
case "limited":
return limitedColor;
case "full":
return fullColor;
}
};

const onItemSelected = (item?: TimeSlot) => {
if (item) {
console.log(`Reserved table for ${item.time}`);
}
};

return (
<Select
modalTitle="Reserve a Table"
modalSubtitle="Select your preferred time slot"
includeSearch={false}
onItemSelected={onItemSelected}
placeholder="Choose time..."
options={timeSlots.filter((s) => s.availability !== "full")}
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Clock size={20} color={iconColor} />
</ListItem.Icon>
<HStack flex={1} justifyContent="space-between" alignItems="center">
<VStack>
<ListItem.Title>{item.time}</ListItem.Title>
<ListItem.Subtitle>Up to {item.guests} guests</ListItem.Subtitle>
</VStack>
<Subhead
marginBottom="$0"
color={getAvailabilityColor(item.availability)}
>
{item.availability === "available" ? "Available" : "2 left"}
</Subhead>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.time}
/>
);
};

Validation Messages

Use the error and success props to display validation indicators in the Select component. You can use the Message component to display validation messages.

Select address...

Please add a shipping address to continue

Select address...

Express delivery available to this address

const ShippingAddressComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$primary.500"].val,
color["$primary.400"].val
);
const defaultBadgeColor = useColorModeValue("$emerald.600", "$emerald.400");

return (
<VStack gap="$4" width="$full">
<VStack>
<Select
error
modalTitle="Shipping Address"
modalSubtitle="Where should we deliver?"
options={addresses}
placeholder="Select address..."
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<MapPin size={20} color={iconColor} />
</ListItem.Icon>
<VStack flex={1}>
<HStack gap="$2" alignItems="center">
<ListItem.Title>{item.label}</ListItem.Title>
{item.isDefault && (
<Subhead marginBottom="$0" color={defaultBadgeColor}>
Default
</Subhead>
)}
</HStack>
<ListItem.Subtitle>{item.address}</ListItem.Subtitle>
</VStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.label}
/>
<Message type="error">
Please add a shipping address to continue
</Message>
</VStack>

<VStack>
<Select
success
value="1"
modalTitle="Shipping Address"
modalSubtitle="Where should we deliver?"
options={addresses}
placeholder="Select address..."
renderItem={({ item }) => (
...
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.label}
/>
<Message type="success">
Express delivery available to this address
</Message>
</VStack>
</VStack>
);
};

With Label

Use the LabelComponent prop to display a label above the Select component. You can also use the required prop to indicate that the field is required.

Select Course

*

Browse courses...

const CourseEnrollmentComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$violet.500"].val,
color["$violet.400"].val
);
const durationColor = useColorModeValue("$primaryGray.600", "$primaryGray.400");

return (
<Select
required
modalTitle="Enroll in a Course"
modalSubtitle="Start your learning journey today"
placeholder="Browse courses..."
options={courses}
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<GraduationCap size={20} color={iconColor} />
</ListItem.Icon>
<VStack flex={1}>
<ListItem.Title>{item.title}</ListItem.Title>
<ListItem.Subtitle>
{item.instructor}{item.level}
</ListItem.Subtitle>
<Subhead marginBottom="$0" color={durationColor}>
{item.duration}
</Subhead>
</VStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.title}
>
<Select.Label>Select Course</Select.Label>
</Select>
);
};

Custom Placeholder

Use the placeholder prop to display a custom placeholder in the Select component.

Add your interests...

const InterestTagsComponent = () => {
return (
<Select
modalTitle="What are you into?"
modalSubtitle="Help us personalize your experience"
placeholder="Add your interests..."
modalSearchPlaceholder="Search interests..."
options={interests}
renderItem={({ item }) => (
<ListItem>
<HStack gap="$3" alignItems="center" flex={1}>
<Body marginBottom="$0" fontSize={24}>
{item.emoji}
</Body>
<ListItem.Title>{item.name}</ListItem.Title>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => `${item.emoji} ${item.name}`}
/>
);
};

Loading Data from API

This example demonstrates how to use the Select component to load data from an external API. The onSearchTermChanged function fetches data based on the user's input, and the initial data is loaded using getExternalOptions.

Choose your country...

const CountryAPIComponent = () => {
const codeColor = useColorModeValue("$primaryGray.500", "$primaryGray.400");
const [loadedCountries, setLoadedCountries] = React.useState<Country[]>([]);

const onSearchTermChanged = async (searchTerm: string) => {
// Simulating API call
await new Promise((resolve) => setTimeout(resolve, 300));
return countries.filter((country) =>
country.name.toLowerCase().includes(searchTerm.toLowerCase())
);
};

useEffect(() => {
// Simulating initial API load
setTimeout(() => setLoadedCountries(countries), 500);
}, []);

return (
<Select
modalTitle="Select Country"
onSearchTermChanged={onSearchTermChanged}
modalSubtitle="Where are you located?"
options={loadedCountries}
placeholder="Choose your country..."
renderItem={({ item }) => (
<ListItem>
<HStack gap="$3" alignItems="center" flex={1}>
<Body marginBottom="$0" fontSize={24}>
{item.flag}
</Body>
<ListItem.Title>{item.name}</ListItem.Title>
<Subhead marginBottom="$0" color={codeColor}>
{item.code}
</Subhead>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => `${item.flag} ${item.name}`}
/>
);
};

Custom Messages

This example illustrates the Select component with custom messages for different states. Use the modalTitle, modalSubtitle, emptyResultsTitle, and emptyResultsSubtitle props to customize the messages.

Select language...

const LanguagePreferenceComponent = () => {
const nativeColor = useColorModeValue("$primaryGray.500", "$primaryGray.400");

return (
<Select
modalTitle="Language"
modalSubtitle="Choose your preferred language"
emptyResultsTitle="Language not found"
emptyResultsSubtitle="We don't support this language yet"
options={languages}
placeholder="Select language..."
renderItem={({ item }) => (
<ListItem>
<HStack flex={1} justifyContent="space-between" alignItems="center">
<ListItem.Title>{item.name}</ListItem.Title>
<Subhead marginBottom="$0" color={nativeColor}>
{item.native}
</Subhead>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.name}
/>
);
};

Override Color Mode

Use the colorMode prop to override the color mode of the Select component.

Select event type...

const EventTypeColorModeComponent = () => {
return (
<Theme colorMode="dark">
<Select
modalTitle="Event Type"
modalSubtitle="What kind of event are you hosting?"
options={eventTypes}
placeholder="Select event type..."
renderItem={({ item }) => (
<ListItem>
<HStack gap="$3" alignItems="center" flex={1}>
<Body marginBottom="$0" fontSize={24}>
{item.icon}
</Body>
<ListItem.Title>{item.name}</ListItem.Title>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => `${item.icon} ${item.name}`}
/>
</Theme>
);
};

Override Accent Color

Use the accentColor prop to override the accent color of the Select component.

Select workout...

const WorkoutTypeComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$rose.500"].val,
color["$rose.400"].val
);

return (
<Theme accentColor="rose">
<Select
modalTitle="Today's Workout"
modalSubtitle="Choose your exercise routine"
options={workoutTypes}
placeholder="Select workout..."
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Dumbbell size={20} color={iconColor} />
</ListItem.Icon>
<HStack justifyContent="space-between" alignItems="center">
<VStack flex={1}>
<ListItem.Title>{item.name}</ListItem.Title>
<ListItem.Subtitle>{item.duration}</ListItem.Subtitle>
</VStack>
<Badge
size="sm"
_container={{ paddingVertical: "$0.5" }}
>
{item.calories} cal
</Badge>
</HStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.name}
/>
</Theme>
);
};

Override Color Mode and Accent Color

Use the colorMode and accentColor props to override the color mode and accent color of the Select component.

Pick a genre...

const MusicGenreComponent = () => {
const { color } = getTokens();
const iconColor = useColorModeValue(
color["$violet.400"].val,
color["$violet.500"].val
);
const statsColor = useColorModeValue("$violet.300", "$violet.600");

return (
<Theme colorMode="dark" accentColor="violet">
<Select
modalTitle="Favorite Genre"
modalSubtitle="What music moves you?"
options={musicGenres}
placeholder="Pick a genre..."
renderItem={({ item }) => (
<ListItem>
<ListItem.Icon>
<Music size={20} color={iconColor} />
</ListItem.Icon>
<VStack flex={1}>
<ListItem.Title>{item.name}</ListItem.Title>
<Subhead marginBottom="$0" color={statsColor}>
{item.artists.toLocaleString()} artists • {item.playlists}{" "}
playlists
</Subhead>
</VStack>
</ListItem>
)}
keyExtractor={(item) => item.id}
displayValueExtractor={(item) => item.name}
/>
</Theme>
);
};