Dropdown

Use Dropdown component to choose option(s) from a list.
Import
JSX
import Dropdown from '@box-kite/react/components/dropdown';
Basic Dropdown
Choice
JSX
<Dropdown label="Choice" defaultValue={1}>
  <Dropdown.Item value={1}>Option 1</Dropdown.Item>
  <Dropdown.Item value={2}>Option 2</Dropdown.Item>
</Dropdown>

Keyboard and roles

This is the APG combobox, whole — in both of its shapes. The trigger is a role="combobox" that keeps DOM focus the entire time; the popup is a role="listbox" of role="option" rows, and the option the arrows are on is named by aria-activedescendant rather than focused. Add isSearchable and the combobox becomes the text field instead of a button. You write none of that — and if you were writing it by hand before, delete it.
Give it a label
A combobox is not named by what it contains: the text in the trigger is its value. Pass label and the component renders it and wires aria-labelledby — or pass your own aria-label in props. Without either, the control has no accessible name, exactly like an input with only a placeholder.
Clear and Select all are options too
Dropdown.Unselect and Dropdown.SelectAll sit inside the listbox, so they carry role="option" and the arrow keys reach them like any other row.
Searchable is the editable combobox
With isSearchable the text field is the combobox — the role, the ARIA and anything you pass in props live on the input, so nothing focusable sits inside anything else focusable. It is a different keyboard map — the one under With isSearchable in the keyboard reference below: the printable keys type instead of navigating, and only Down and Up reach the listbox.
Controlled Dropdown
JSX
const [selectedValue, setSelectedValue] = useState<number>(2);

<Dropdown value={selectedValue} onValueChange={(value) => setSelectedValue(value as number)}>
  <Dropdown.Item value={1}>Option 1</Dropdown.Item>
  <Dropdown.Item value={2}>Option 2</Dropdown.Item>
  <Dropdown.Item value={3}>Option 3</Dropdown.Item>
</Dropdown>
Unselect Item
JSX
<Dropdown>
  <Dropdown.Unselect>Select</Dropdown.Unselect>
  <Dropdown.Item value={1}>Option 1</Dropdown.Item>
  <Dropdown.Item value={2}>Option 2</Dropdown.Item>
</Dropdown>
Disabled
JSX
<Dropdown disabled width={50}>
  <DropdownUnselect>Select</DropdownUnselect>
  <DropdownItem value={1}>Option 1</DropdownItem>
  <DropdownItem value={2}>Option 2</DropdownItem>
</Dropdown>
Compact
JSX
<Dropdown variant="compact" width={40}>
  <DropdownUnselect>Select</DropdownUnselect>
  <DropdownItem value={1}>Option 1</DropdownItem>
  <DropdownItem value={2}>Option 2</DropdownItem>
</Dropdown>
Custom Variant (outlined)
JSX
// boxExtends.ts — register the variant, and export what you registered.
export const components = Box.components({
  dropdown: {
    variants: {
      outlined: {
        bgColor: 'transparent', b: 2, borderColor: 'indigo-500', color: 'indigo-600',
      },
    },
    children: {
      item: { variants: { outlined: { hover: { bgColor: 'indigo-50' }, selected: { bgColor: 'indigo-100' } } } },
      items: { variants: { outlined: { b: 2, borderColor: 'indigo-500' } } },
    },
  },
});

// box.d.ts — teach TypeScript the name, or variant="outlined" stays a type error.
import { ExtractComponentsAndVariants } from '@box-kite/core/types';
import { components } from './boxExtends';

declare module '@box-kite/core/types' {
  namespace Augmented {
    interface ComponentsTypes extends ExtractComponentsAndVariants<typeof components> {}
  }
}

// Use — the variant propagates to all children automatically.
<Dropdown variant="outlined">
  <Dropdown.Item value={1}>Option 1</Dropdown.Item>
  <Dropdown.Item value={2}>Option 2</Dropdown.Item>
</Dropdown>
Searchable
User
Select
JSX
<Dropdown
  label="User"
  isSearchable
  searchPlaceholder="Search users..."
  width={50}
>
  <DropdownUnselect>Select</DropdownUnselect>
  <DropdownItem value={1}>John Doe</DropdownItem>
  <DropdownItem value={2}>Joe Smith</DropdownItem>
  <DropdownItem value={3}>Alice</DropdownItem>
  <DropdownItem value={4}>Bob</DropdownItem>
</Dropdown>
Searchable with Empty Item
User
Select
JSX
<Dropdown
  label="User"
  isSearchable
  searchPlaceholder="Search users..."
  width={50}
>
  <DropdownEmptyItem>No options</DropdownEmptyItem>
  <DropdownUnselect>Select</DropdownUnselect>
  <DropdownItem value={1}>John Doe</DropdownItem>
  <DropdownItem value={2}>Joe Smith</DropdownItem>
  <DropdownItem value={3}>Alice</DropdownItem>
  <DropdownItem value={4}>Bob</DropdownItem>
</Dropdown>
Multiple Selection
JSX
<Dropdown multiple width={50}>
  <DropdownEmptyItem>No options</DropdownEmptyItem>
  <DropdownUnselect>Unselect All</DropdownUnselect>
  <DropdownSelectAll>Select All</DropdownSelectAll>
  <DropdownItem value={1}>John Doe</DropdownItem>
  <DropdownItem value={2}>Joe Smith</DropdownItem>
  <DropdownItem value={3}>Alice</DropdownItem>
  <DropdownItem value={4}>Bob</DropdownItem>
</Dropdown>
Multiple Selection with Checkboxes
JSX
<Dropdown multiple showCheckbox width={50}>
  <DropdownEmptyItem>No options</DropdownEmptyItem>
  <DropdownUnselect>Unselect All</DropdownUnselect>
  <DropdownSelectAll>Select All</DropdownSelectAll>
  <DropdownItem value={1}>John Doe</DropdownItem>
  <DropdownItem value={2}>Joe Smith</DropdownItem>
  <DropdownItem value={3}>Alice</DropdownItem>
  <DropdownItem value={4}>Bob</DropdownItem>
</Dropdown>
Multiple with Custom Display
JSX
<Dropdown multiple showCheckbox width={50}>
  <DropdownDisplay />
  <DropdownEmptyItem>No options</DropdownEmptyItem>
  <DropdownUnselect>Unselect All</DropdownUnselect>
  <DropdownSelectAll>Select All</DropdownSelectAll>
  <DropdownItem value={1}>John Doe</DropdownItem>
  <DropdownItem value={2}>Joe Smith</DropdownItem>
  <DropdownItem value={3}>Alice</DropdownItem>
  <DropdownItem value={4}>Bob</DropdownItem>
</Dropdown>

Select

Data-driven dropdown — pass data + def instead of composing children. Wraps Dropdown internally.
Import
JSX
import Select from '@box-kite/react/components/select';
Basic Select
User
JSX
const users = [
  { id: 1, name: 'John Doe', role: 'Admin' },
  { id: 2, name: 'Joe Smith', role: 'Editor' },
  { id: 3, name: 'Alice Brown', role: 'Viewer' },
];

<Select
  label="User"
  data={users}
  def={{ valueKey: 'id', displayKey: 'name', placeholder: 'Pick a user...' }}
  width={50}
/>
Custom Item Display
JSX
<Select
  data={users}
  def={{
    valueKey: 'id',
    display: (user) => `${user.name} — ${user.role}`,
    placeholder: 'Pick a user...',
  }}
/>
Multiple with Search
Users
Pick users...
JSX
<Select
  data={users}
  def={{
    valueKey: 'id',
    displayKey: 'name',
    placeholder: 'Pick users...',
    selectAllText: 'Select all',
    emptyText: 'No users found',
    selectedDisplay: (rows) =>
      rows.length === 0 ? 'Pick users...' : `${rows.length} selected`,
  }}
  label="Users" multiple showCheckbox isSearchable searchPlaceholder="Search users..."
/>