Select
import Select from "@intility/bifrost-react-select";
Install package
The Select component is published as a separate @intility/bifrost-react-select
package:
- Run the following command to install:
npm install @intility/bifrost-react-select
npm install @intility/bifrost-react-select
- Import component separately from other components
import Select from "@intility/bifrost-react-select";
import Select from "@intility/bifrost-react-select";
- Use it in your JSX code
<Select label="Country" options={countries} />
<Select label="Country" options={countries} />
Options and state
You can control and access the options and state of the select with the following props:
options
- an array of objects withlabel
(displayed string) andvalue
(any data you want associated) properties.value
- sets currently selected optiononChange
- function triggered when user selects an option, with the option object as argument
Commonly used props
isClearable
Use isClearable
prop for possibility to remove selected option with button.
Select an option and you should see an "x" icon.
<Select isClearable />
<Select isClearable />
state and feedback
Select
can indicate an alert state based on input. Set state
prop to
'alert'
to style it accordingly. Meanwhile, use feedback
to provide
additional information.
Use the required
prop to render Select
as required. This will add
(required)
text after the label. You can hide this label (but still have the
select be required) with requiredNoLabel
.
<Select state="alert" feedback="Missing value" required />
<Select state="alert" feedback="Missing value" required />
isMulti
Using the isMulti
prop makes it possible to select multiple options. This will
make the onChange
callback receive an array instead of a single option.
<Select
isMulti
onChange={(selectedOptionsArray) => setSelected(selectedOptionsArray)}
/>
<Select
isMulti
onChange={(selectedOptionsArray) => setSelected(selectedOptionsArray)}
/>
Grouped options
The array pased to the options
prop can contain objects with a label
and
its own nested options
array, which lets you group options. Also works with
isMulti
.
<Select
options={[
{
label: "Marvel",
options: [
{ value: "Iron Man", label: "Iron Man" },
{ value: "Spider-man", label: "Spider-man" },
{ value: "Star Lord", label: "Star Lord" },
],
},
{
label: "DC",
options: [
{ value: "Superman", label: "Superman" },
{ value: "Batman", label: "Batman" },
{ value: "The Flash", label: "The Flash" },
],
},
]}
/>
<Select
options={[
{
label: "Marvel",
options: [
{ value: "Iron Man", label: "Iron Man" },
{ value: "Spider-man", label: "Spider-man" },
{ value: "Star Lord", label: "Star Lord" },
],
},
{
label: "DC",
options: [
{ value: "Superman", label: "Superman" },
{ value: "Batman", label: "Batman" },
{ value: "The Flash", label: "The Flash" },
],
},
]}
/>
isDisabled
Disable a <Select>
with isDisabled
prop, or disable an option with
isDisabled: true
property on the option object.
<Select label='Disabled Select' isDisabled />
<Select
label='Disabled Denmark option'
options={[
{ value: 'Norway', label: 'Norway' },
{ value: 'Sweden', label: 'Sweden' },
{ value: 'Denmark', label: 'Denmark', isDisabled: true },
{ value: 'Germany', label: 'Germany' }
]}
/>
<Select label='Disabled Select' isDisabled />
<Select
label='Disabled Denmark option'
options={[
{ value: 'Norway', label: 'Norway' },
{ value: 'Sweden', label: 'Sweden' },
{ value: 'Denmark', label: 'Denmark', isDisabled: true },
{ value: 'Germany', label: 'Germany' }
]}
/>
loading
The loading
prop displays a loading spinner on the right hand side of the
input.
<Select loading />
<Select loading />
hideLabel
The label
prop is required, but you can hide it with hideLabel
.
<Select label="Country" hideLabel />
<Select label="Country" hideLabel />
small
The small
prop reduces the height if the input field. It will still stretch
to acommodate multi-select badges.
<Select label="Small select" small />
<Select label="Small select" small />
Advanced
AsyncSelect
<AsyncSelect>
can be used to load options from a source as the user types.
Try type 'No' in the demo below
import { useState } from "react";
import { AsyncSelect } from "@intility/bifrost-react-select";
const countries = [
{ value: "Norway", label: "Norway" },
{ value: "Sweden", label: "Sweden" },
{ value: "Denmark", label: "Denmark" },
{ value: "Germany", label: "Germany" },
];
const [selected, setSelected] = useState();
function getAsyncOptions(inputValue) {
return new Promise((resolve, reject) => {
const filtered = countries.filter((c) =>
String(c.label.toLowerCase()).startsWith(inputValue.toLowerCase()),
);
resolve(filtered.slice(0, 3));
});
}
<AsyncSelect
label="Country"
placeholder="- Select country -"
loadOptions={(inputValue) => getAsyncOptions(inputValue)}
onChange={(item) => setSelected(item)}
isClearable
/>;
import { useState } from "react";
import { AsyncSelect } from "@intility/bifrost-react-select";
const countries = [
{ value: "Norway", label: "Norway" },
{ value: "Sweden", label: "Sweden" },
{ value: "Denmark", label: "Denmark" },
{ value: "Germany", label: "Germany" },
];
const [selected, setSelected] = useState();
function getAsyncOptions(inputValue) {
return new Promise((resolve, reject) => {
const filtered = countries.filter((c) =>
String(c.label.toLowerCase()).startsWith(inputValue.toLowerCase()),
);
resolve(filtered.slice(0, 3));
});
}
<AsyncSelect
label="Country"
placeholder="- Select country -"
loadOptions={(inputValue) => getAsyncOptions(inputValue)}
onChange={(item) => setSelected(item)}
isClearable
/>;
CreatableSelect
<CreatableSelect>
can be used to create new options.
Try to type 'England' and add the new option to the component
import { useState } from "react";
import { CreatableSelect } from "@intility/bifrost-react-select";
const countries = [
{ value: "Norway", label: "Norway" },
{ value: "Sweden", label: "Sweden" },
{ value: "Denmark", label: "Denmark" },
{ value: "Germany", label: "Germany" },
];
const [selected, setSelected] = useState();
const [options, setOptions] = useState(countries);
const handleCreate = (option) => {
const newOption = {
value: option,
label: option,
};
setOptions((options) => [...options, newOption]);
setSelected(newOption);
};
<CreatableSelect
label="Country"
placeholder="- Select country -"
options={options}
value={selected}
onChange={(item) => setSelected(item)}
onCreateOption={(option) => handleCreate(option)}
isClearable
/>;
import { useState } from "react";
import { CreatableSelect } from "@intility/bifrost-react-select";
const countries = [
{ value: "Norway", label: "Norway" },
{ value: "Sweden", label: "Sweden" },
{ value: "Denmark", label: "Denmark" },
{ value: "Germany", label: "Germany" },
];
const [selected, setSelected] = useState();
const [options, setOptions] = useState(countries);
const handleCreate = (option) => {
const newOption = {
value: option,
label: option,
};
setOptions((options) => [...options, newOption]);
setSelected(newOption);
};
<CreatableSelect
label="Country"
placeholder="- Select country -"
options={options}
value={selected}
onChange={(item) => setSelected(item)}
onCreateOption={(option) => handleCreate(option)}
isClearable
/>;
Replace components
react-select
allows you to replace internal
components which allows for more advanced
use cases.
Bifrost replaces the following components internally:
<ClearIndicator>
<DropdownIndicator>
<Input>
<LoadingIndicator>
<MenuList>
<Option>
To use or wrap our components in your own overrides, you can import
selectComponents
from @intility/bifrost-react-select
import { selectComponents } from "@intility/bifrost-react-select";
// ...
<selectComponents.Option>...</selectComponents.Option>;
import { selectComponents } from "@intility/bifrost-react-select";
// ...
<selectComponents.Option>...</selectComponents.Option>;
Display number of selections
Let's say you have a multi-select, but don't want to display a badge for each
selected item, but something like "Selected (4)" instead, you can replace the
MultiValue
component:
CustomMultiValue.js
import { selectComponents } from "@intility/bifrost-react-select";
export default function CustomMultiValue(props) {
const totalSelected = props.getValue().length;
// render the default badges if two or fewer options are selected
const maxToShow = 2;
if (totalSelected <= maxToShow) {
return <selectComponents.MultiValue {...props} />;
}
// don't show selected count while filtering,
// and avoid showing selected count more than once (for index 0)
const inputValue = props.selectProps.inputValue;
if (!inputValue && props.index === 0) {
return <>Selected ({totalSelected})</>;
} else {
return <></>;
}
}
import { selectComponents } from "@intility/bifrost-react-select";
export default function CustomMultiValue(props) {
const totalSelected = props.getValue().length;
// render the default badges if two or fewer options are selected
const maxToShow = 2;
if (totalSelected <= maxToShow) {
return <selectComponents.MultiValue {...props} />;
}
// don't show selected count while filtering,
// and avoid showing selected count more than once (for index 0)
const inputValue = props.selectProps.inputValue;
if (!inputValue && props.index === 0) {
return <>Selected ({totalSelected})</>;
} else {
return <></>;
}
}
Then supply the component to your Select:
import CustomMultiValue from "./CustomMultiValue";
<Select
components={{
MultiValue: CustomMultiValue,
}}
// ...
/>;
import CustomMultiValue from "./CustomMultiValue";
<Select
components={{
MultiValue: CustomMultiValue,
}}
// ...
/>;
Try it yourself
Interactive demo including typed props: