> For AI agents: the complete documentation index is available at /ooui-react/en/llms.txt, the full documentation bundle is available at /ooui-react/en/llms-full.txt.

# ButtonSelect

> [Source](https://github.com/BearBin1215/ooui-react/tree/main/src/widgets/ButtonSelect) | [Original component](https://doc.wikimedia.org/oojs-ui/master/js/OO.ui.ButtonSelectWidget.html "OO.ui.ButtonSelectWidget")

A button select: a set of mutually exclusive options shown as a row of buttons. The option data contract is in [Selection and options](/ooui-react/en/guide/options.md).

## Basic usage

```tsx preview
import { useState } from "react";
import { ButtonSelect } from "ooui-react";

const options = [
  { value: "left", icon: "alignLeft", children: "Align left" },
  { value: "center", icon: "alignCenter", children: "Center" },
  { value: "right", icon: "alignRight", children: "Align right" },
];

function App() {
  const [align, setAlign] = useState<string | number>("left");

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      <ButtonSelect options={options} value={align} onChange={setAlign} aria-label="Alignment" />
      <div>Current alignment: {String(align)}</div>
    </div>
  );
}

export default App;
```

## Unframed and disabled items

Options support `framed={false}`; items with `disabled` are not selectable, and a group-level `disabled` disables the whole group (see [Selection and options · Disabled](/ooui-react/en/guide/options.md#disabled)).

```tsx preview
import { ButtonSelect } from "ooui-react";

function App() {
  return (
    <ButtonSelect
      defaultValue="a"
      options={[
        { value: "a", children: "Enabled" },
        { value: "b", children: "Disabled", disabled: true },
        { value: "c", children: "Also enabled" },
      ]}
    />
  );
}

export default App;
```

## Keyboard

After a click, focus moves into the group automatically (slightly better than the original, which leaves focus where it was so the arrow keys stay dead), and ↑↓←→ then **cycle among non-disabled items and select directly**; Enter re-affirms the current item. Pressing Tab also moves focus into the group. This is the "direct-select family" keyboard model (shared by [TabSelect](/ooui-react/en/components/tab-select/index.md) and [RadioSelect](/ooui-react/en/components/radio-select/index.md)).

## API

| Prop           | Description                                                                                                                               | Type                              | Default |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |
| `options`      | Option set (**required**); each item has `value` and `children` (text), optionally `icon` / `indicator` / `flags` / `framed` / `disabled` | `ButtonSelectOptionProps[]`       | —       |
| `value`        | Current selected value (controlled)                                                                                                       | `string \| number`                | —       |
| `defaultValue` | Initial selected value for uncontrolled use                                                                                               | `string \| number`                | —       |
| `onChange`     | Selected-value change callback (value-first)                                                                                              | `ChangeHandler<string \| number>` | —       |
| `disabled`     | Whether disabled (also disables every option in the group)                                                                                | `boolean`                         | `false` |
| `tabIndex`     | Tab order (focus rests on the group)                                                                                                      | `number \| null`                  | `0`     |
| `...rest`      | Native `div` props (`className`, `id`, `aria-*`, etc.) passed straight to the root                                                        | `HTMLAttributes<HTMLDivElement>`  | —       |

## Differences from OOUI

- **Initially selected framed options are inverted too**: the original inverts only after a user click while initially selected ones stay normal; this library applies the theme rule uniformly — active or disabled means inverted. {/* deviations: dev-buttonoption-invert */}

## See also

- Tab-style direct select: [TabSelect](/ooui-react/en/components/tab-select/index.md)
- Radio group (native radio semantics): [RadioSelect](/ooui-react/en/components/radio-select/index.md)
- Option data and the keyboard focus model: [Selection and options](/ooui-react/en/guide/options.md)
