Skip to main content
/
/
/
Select

Select

import Select from "@intility/bifrost-react-select";

More props

The Select component uses react-select under the hood. See react-select props docs for full documentation.

Install package

The Select component is published as a separate @intility/bifrost-react-select package:

  1. Run the following command to install:
npm install @intility/bifrost-react-select
npm install @intility/bifrost-react-select
  1. Import component separately from other components
import Select from "@intility/bifrost-react-select";
import Select from "@intility/bifrost-react-select";
  1. 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 with label (displayed string) and value (any data you want associated) properties.
  • value - sets currently selected option
  • onChange - function triggered when user selects an option, with the option object as argument
import { useState } from "react";
import Button from "@intility/bifrost-react/Button";
import Select from "@intility/bifrost-react-select";

const countries = [
  { value: "Norway", label: "Norway" },
  { value: "Sweden", label: "Sweden" },
  { value: "Denmark", label: "Denmark" },
  { value: "Germany", label: "Germany" },
];

export default function SelectSandbox() {
  const [selected, setSelected] = useState(countries[2]);
  return (
    <div className="bf-page-padding">
      <Select
        label="Country"
        placeholder="- Select country -"
        description="Select your country of residence"
        options={countries}
        value={selected}
        onChange={(item) => setSelected(item)}
      />
      <p>Selected item: {selected.label}</p>
      <Button onClick={() => setSelected(countries[0])}>
        Select first option
      </Button>
    </div>
  );
}

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.

Read more

See usage demo at Forms example

<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)} />
Denmark
Finland
France

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, }} // ... />;
Select countries

Try it yourself

Interactive demo including typed props:

import { useState } from "react";
import Select, { selectComponents } from "@intility/bifrost-react-select";
import { GroupBase, MultiValueProps } from "react-select";

const CustomMultiValue = <
  Option,
  IsMulti extends boolean,
  Group extends GroupBase<Option>,
>(
  props: MultiValueProps<Option, IsMulti, Group>,
) => {
  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 <></>;
  }
};

const countries = [
  { value: "Norway", label: "Norway" },
  { value: "Sweden", label: "Sweden" },
  { value: "Denmark", label: "Denmark" },
  { value: "Finland", label: "Finland" },
  { value: "France", label: "France" },
  { value: "Spain", label: "Spain" },
  { value: "Italy", label: "Italy" },
  { value: "Germany", label: "Germany" },
];

export default function SelectCountDemo() {
  const [selected, setSelected] = useState<
    readonly (typeof countries)[number][]
  >([]);

  return (
    <Select
      label="Countries"
      placeholder="Select countries"
      options={countries}
      value={selected}
      onChange={setSelected}
      isMulti
      // pass in the custom override
      components={{
        MultiValue: CustomMultiValue,
      }}
    />
  );
}