Select

Select dropdowns are appropriate when you are allowing the user to choose between many options. If there are only a few options to choose from, prefer the RadioButton component.

Note: This component uses @headlessui/react's Listbox component.

Source code
import { Select } from "rfui-package";

#Basic

<Select
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Using with HTML forms

If you add the name prop, a hidden input element will be rendered and kept in sync with theSelect state. See Headless UI's docs here.
<Select
  name="name-example"
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Empty initial value

If you want an empty initial value use something like this as the first option in the options array:

{
  label: "",
  value: "",
}
<Select
  options={[
    {
      label: "",
      value: "",
    },
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Uncontrolled

If you don't pass onChange this component will be uncontrolled. If you're taking the uncontrolled approach you can use the defaultValue prop to set the initial value.
<Select
  defaultValue={uncontrolledOptions[1].value}
  options={uncontrolledOptions}
/>

#Controlled

Pass value and onChange to make this a controlled component.
<Select
  value={controlledValue}
  onChange={(newValue) => {
    setControlledValue(newValue as { label: string; value: string });
  }}
  options={controlledOptions}
/>

#Size

Set size to either "sm", "md" or "lg". Defaults to "md".
<Stack className="w-fit gap-5">
  <Select
    size="sm"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
  <Select
    size="md"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
  <Select
    size="lg"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
</Stack>

#Width

To set the width use buttonClassName and optionsClassName.
<Select
  buttonClassName="w-[500px]"
  optionsClassName="w-[500px]"
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Rounded

Set rounded to either "square", "sm", "lg", or "full". Defaults to the value of the CSS variable --default-roundedness. See "Default roundedness".
<Stack className="w-fit gap-5">
  <Select
    rounded="square"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
  <Select
    rounded="sm"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
  <Select
    rounded="lg"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
  <Select
    rounded="full"
    options={[
      {
        label: "Foo",
        value: "foo",
      },
      {
        label: "Bar",
        value: "bar",
      },
      {
        label: "Baz",
        value: "baz",
      },
    ]}
  />
</Stack>

#Disabled

Set disabled to true.
<Select
  disabled
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Disabled option

Set disabled to true for a given option .
<Select
  options={[
    {
      label: "Foo",
      value: "foo",
      disabled: false,
    },
    {
      label: "Bar",
      value: "bar",
      disabled: true,
    },
    {
      label: "Baz",
      value: "baz",
      disabled: false,
    },
  ]}
/>

#Invalid

Set invalid totrue.
<Select
  invalid
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
  ]}
/>

#Uncontrolled multiselect

Set multiple to true. If using defaultValue pass an array of options.
<Select
  multiple
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
    {
      label:
        "Some long text here causing the display to show 'n item(s) selected'",
      value: "long",
    },
  ]}
/>

#Controlled multiselect

Set multiple to true and pass an array to value.
<Select
  multiple
  value={controlledMultiselectValue}
  onChange={(newValues) => {
    setControlledMultiselectValue(
      newValues as { label: string; value: string }[]
    );
  }}
  options={[
    {
      label: "Foo",
      value: "foo",
    },
    {
      label: "Bar",
      value: "bar",
    },
    {
      label: "Baz",
      value: "baz",
    },
    {
      label:
        "Some long text here causing the display to show 'n item(s) selected'",
      value: "long",
    },
  ]}
/>

#Props

PropRequiredDefaultType and notes
options-
Option[]
name--
string
Use if you want to submit as an HTML form. See Headless UI's docs.
size-"md"
"sm" | "md" | "lg"
rounded--
"square" | "sm" | "lg" | "full"
Defaults to the value of the CSS variable --default-roundedness. See "Default roundedness".
disabled-false
boolean
invalid-false
boolean
defaultValue--
Option | Option[]
value--
Option | Option[]
onChange--
(newValue: Option | Option[]) => void
multiple-false
boolean
buttonClassName--
string
This will be passed to Headless UI's ListboxButton component.
optionsClassName--
string
This will be passed to Headless UI's ListboxOptions component.
optionClassName--
string
This will be passed to Headless UI's ListboxOption component.