Select
Input field with multiple options in a dropdown
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- Import component separately from other components
import Select from "@intility/bifrost-react-select";- Use it in your JSX code
<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.
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.
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.
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.
isDisabled
Disable a <Select> with isDisabled prop, or disable an option with
isDisabled: true property on the option object.
loading
The loading prop displays a loading spinner on the right hand side of the
input.
hideLabel
The label prop is required, but you can hide it with hideLabel.
small
The small prop reduces the height if the input field. It will still stretch
to acommodate multi-select badges.
AsyncSelect
<AsyncSelect> can be used to load options from a source as the user types.
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.
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>;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 <></>;
}
}Then supply the component to your Select:
<Select
components={{
MultiValue: CustomMultiValue,
}}
// ...
/>Hierarchy
If you only need two levels, and the top level should not be selectable, see Grouped options above.
The <Select> component doesn't support hierarchy directly, but you can fake it
by indenting:
- Add a
levelfield to your list ofoptions. - Create a
<CustomOption>wrappingselectComponents.Optionto inherit default styling and functionality. - Apply a
paddingLeftbased onlevelthroughinnerProps.style. - Override the default internal
Optionusing thecomponentsprop.
CustomOption.js
import { selectComponents } from "@intility/bifrost-react-select";
export default function CustomOption(props) {
const level = props.data.level ?? 0;
return (
<selectComponents.Option
{...props}
innerProps={{
...props.innerProps,
style: { ...props.innerProps.style, paddingLeft: 12 + level * 16 },
}}
/>
);
}Then supply the component to your Select:
<Select
components={{
Option: CustomOption,
}}
// ...
/>