# Button Group
> Button groups are a collection of related buttons.

## Import

```js
import { ButtonGroup, ToggleButtonGroup } from '@gemini-suite/vera-react';

// you may also access context via hooks:
// import { useButtonGroupContext, useToggleButtonGroupContext } from '@gemini-suite/vera-react';
```

Button Group is a compound component that consists of multiple parts:

- `ButtonGroup.Root`: A container that groups buttons together.
- `ButtonGroup.Button`: An individual group item, which composes [Button component](/components/button).

Toggle Button Group is a compound component that consists of multiple parts:

- `ToggleButtonGroup.Root`: A container that allows to use grouped items as a checkbox or radio buttons.
- `ToggleButtonGroup.Button`: An individual group item, which composes [Button component](/components/button).

## Examples

### Basic

Button groups can be used to display set of actions that have a relationship in a "united" visual.

```jsx
<ButtonGroup.Root>
  <ButtonGroup.Button>{'Cut'}</ButtonGroup.Button>
  <ButtonGroup.Button>{'Copy'}</ButtonGroup.Button>
  <ButtonGroup.Button>{'Paste'}</ButtonGroup.Button>
</ButtonGroup.Root>
```

They are often used for various kinds of filtering or as a switch between different views.

```jsx
<ButtonGroup.Root aria-label="View">
  <ButtonGroup.Button>{'Map'}</ButtonGroup.Button>
  <ButtonGroup.Button isActive>{'Hybrid'}</ButtonGroup.Button>
  <ButtonGroup.Button>{'Satellite'}</ButtonGroup.Button>
</ButtonGroup.Root>
```

### Variants

There are two visual variants, which set the visual priorities of the grouped buttons: `outline` and `strong`.

The default, `outline` variant is best for actions that are important but not primary in your app.

```jsx
<ButtonGroup.Root>
  <ButtonGroup.Button>
    <Flex gap="spacingS">
      {'Active'}
      <Label circular className="fill-accent10 zeta">
        {'5'}
      </Label>
    </Flex>
  </ButtonGroup.Button>
  <ButtonGroup.Button>
    <Flex gap="spacingS">
      {'Inactive'}
      <Label circular className="fill-accent10 zeta">
        {'18'}
      </Label>
    </Flex>
  </ButtonGroup.Button>
</ButtonGroup.Root>
```

Use `strong` variant only to contain actions that are high emphasis.

```jsx
<ButtonGroup.Root variant="strong">
  <ButtonGroup.Button leftIcon={<SvgIcon iconName="send" />}>
    {'Send'}
  </ButtonGroup.Button>
  <Menu.Root>
    <Menu.Trigger
      as={ButtonGroup.Button}
      withLoneIcon
      aria-label="More options"
    >
      <SvgIcon iconName="chevronDown" />
    </Menu.Trigger>
    <Menu.Content anchorOffset={4}>
      <Menu.Item startElement={<SvgIcon iconName="calendar" />}>
        {'Schedule for later'}
      </Menu.Item>
      <Menu.Item startElement={<SvgIcon iconName="bookmark" />}>
        {'Save draft'}
      </Menu.Item>
    </Menu.Content>
  </Menu.Root>
</ButtonGroup.Root>
```

### Sizing

Use `size` property to apply shared size for every button in a group. Available sizes are `medium` and `small`.
[See Button sizes](/components/button/#sizes).

```jsx
<Flex flow="column">
  <ButtonGroup.Root size="medium">
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
  <ButtonGroup.Root size="small">
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
</Flex>
```

### Layout

Use `layout` property to change how buttons are laid out.

- `inline` (default) - the group acts as an inline-level box and the buttons are sized according to their content.
- `stretch` - the group fills the container and the buttons are equal in width.

```jsx
<Flex flow="column">
  <ButtonGroup.Root layout="inline">
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
  <ButtonGroup.Root layout="stretch">
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
</Flex>
```

### Disabled state

Entire button group or isolated buttons can be disabled with the help of `isDisabled` property.

```jsx
<Flex flow="column">
  <ButtonGroup.Root isDisabled>
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
  <ButtonGroup.Root>
    <ButtonGroup.Button>{'Week'}</ButtonGroup.Button>
    <ButtonGroup.Button isDisabled>{'Month'}</ButtonGroup.Button>
    <ButtonGroup.Button>{'Year'}</ButtonGroup.Button>
  </ButtonGroup.Root>
</Flex>
```

### With icon buttons

Groups can contain [icon only buttons](/components/button#icon-only-button).

<Callout variant="important">

Please provide `aria-label` prop to support assistive technology (i.e. screen readers) or wrap the button with a [tooltip](/components/tooltip).

</Callout>

```jsx
<Flex flow="column">
  <ButtonGroup.Root>
    <Tooltip delay={300} content="Zoom in">
      <ButtonGroup.Button withLoneIcon>
        <SvgIcon iconName="add" />
      </ButtonGroup.Button>
    </Tooltip>
    <Tooltip delay={300} content="Zoom out">
      <ButtonGroup.Button withLoneIcon>
        <SvgIcon iconName="minus" />
      </ButtonGroup.Button>
    </Tooltip>
  </ButtonGroup.Root>
  <ButtonGroup.Root>
    <Tooltip delay={300} content="Align left">
      <ButtonGroup.Button withLoneIcon>
        <SvgIcon iconName="alignLeft" />
      </ButtonGroup.Button>
    </Tooltip>
    <Tooltip delay={300} content="Align center">
      <ButtonGroup.Button withLoneIcon>
        <SvgIcon iconName="alignCenter" />
      </ButtonGroup.Button>
    </Tooltip>
    <Tooltip delay={300} content="Align right">
      <ButtonGroup.Button withLoneIcon>
        <SvgIcon iconName="alignRight" />
      </ButtonGroup.Button>
    </Tooltip>
  </ButtonGroup.Root>
</Flex>
```

### Split buttons

Use button group to create split buttons.
Split buttons are useful for exposing a primary action that is most most commonly accessed while nesting secondary, less frequently used actions until needed.
This makes them a nice pattern to helping a busy design feel more minimal.

Example below shows how a button in the group can be used to trigger a dropdown menu from the [Menu component](/components/menu).

```jsx
<Flex>
  <Button variant="outline">{'Cancel'}</Button>
  <ButtonGroup.Root variant="strong">
    <ButtonGroup.Button>{'Save'}</ButtonGroup.Button>
    <Menu.Root>
      <Menu.Trigger
        as={ButtonGroup.Button}
        withLoneIcon
        aria-label="More options"
      >
        <SvgIcon iconName="chevronDown" />
      </Menu.Trigger>
      <Menu.Content anchorOffset={4} placement="bottom_right">
        <Menu.Item>{'Save as…'}</Menu.Item>
        <Menu.Item>{'Save all'}</Menu.Item>
      </Menu.Content>
    </Menu.Root>
  </ButtonGroup.Root>
</Flex>
```

Split buttons can also be set in `small` size:

```jsx
<ButtonGroup.Root variant="strong" size="small">
  <ButtonGroup.Button>{'Save'}</ButtonGroup.Button>
  <Menu.Root>
    <Menu.Trigger
      as={ButtonGroup.Button}
      withLoneIcon
      aria-label="More options"
    >
      <SvgIcon iconName="chevronDown" />
    </Menu.Trigger>
    <Menu.Content size="small" anchorOffset={2} placement="bottom_right">
      <Menu.Item>{'Save as…'}</Menu.Item>
      <Menu.Item>{'Save all'}</Menu.Item>
    </Menu.Content>
  </Menu.Root>
</ButtonGroup.Root>
```

### With overflow Menu

Button groups work best with a limited set of items. If there are more than three items in the group, be thoughtful about how a long list of buttons might appear on small screens.
Overflow [Menu](/components/menu) can be used when the button group is larger than its containing space or to preserve space.

```jsx
<ButtonGroup.Root>
  <ButtonGroup.Button>{'Find'}</ButtonGroup.Button>
  <ButtonGroup.Button>{'Find previous'}</ButtonGroup.Button>
  <Menu.Root>
    <Menu.Trigger
      as={ButtonGroup.Button}
      withLoneIcon
      aria-label="More options"
    >
      <SvgIcon iconName="more" />
    </Menu.Trigger>
    <Menu.Content anchorOffset={4} placement="bottom_right">
      <Menu.Item>{'Find all'}</Menu.Item>
    </Menu.Content>
  </Menu.Root>
</ButtonGroup.Root>
```

### Toggle button group

`ToggleButtonGroup` is a specialized kind of button group that allows to toggle between or choose multiple items to make a selection.

In `single` type, the button group functions similarly to a [radio group](/components/forms/radio#radiogroup). Only one button in the group can be selected at a time.

<Callout variant="important">

Remember to provide `aria-label` for the toggle button group or linking it to
an existing label via `aria-labelledby`.

</Callout>

<Callout variant="tip">

For toggling between on/off states, consider using the [Switch component](/components/switch).

</Callout>

```jsx
<Flex flow="column" gap="spacingXs">
  <Text color="foregroundNeutralSubtle" id="layoutToggleLabel">
    {'Layout'}
  </Text>
  <ToggleButtonGroup.Root
    type="single"
    aria-labelledby="layoutToggleLabel"
    defaultValue="grid"
  >
    <ToggleButtonGroup.Button
      value="grid"
      leftIcon={<SvgIcon iconName="grid" />}
    >
      {'Grid'}
    </ToggleButtonGroup.Button>
    <ToggleButtonGroup.Button
      value="stack"
      leftIcon={<SvgIcon iconName="list" />}
    >
      {'List'}
    </ToggleButtonGroup.Button>
  </ToggleButtonGroup.Root>
</Flex>
```

In `multiple` type, the button group functions similarly to a [group of checkboxes](components/forms/checkbox#checkboxgroup). Multiple buttons can be selected at the same time.
Use only when a small list of options can be selected from.

```jsx
<ToggleButtonGroup.Root type="multiple" aria-label="Formatting options">
  <ToggleButtonGroup.Button value="bold" withLoneIcon aria-label="Bold">
    <SvgIcon iconName="bold" />
  </ToggleButtonGroup.Button>
  <ToggleButtonGroup.Button value="italic" withLoneIcon aria-label="Italic">
    <SvgIcon iconName="italic" />
  </ToggleButtonGroup.Button>
  <ToggleButtonGroup.Button
    value="underline"
    withLoneIcon
    aria-label="Underline"
  >
    <SvgIcon iconName="underline" />
  </ToggleButtonGroup.Button>
</ToggleButtonGroup.Root>
```

### Preselected toggle button group

`ToggleButtonGroup` works in an uncontrolled way by default, meaning each `ToggleButtonGroup` component instance is responsible for managing selected value(s) internally.
You can preselect toggle button group value or values (depending on the `type`) by using `defaultValue` property.

```jsx
<ToggleButtonGroup.Root
  type="multiple"
  aria-label="Formatting options"
  defaultValue={['bold', 'underline']}
>
  <ToggleButtonGroup.Button value="bold" withLoneIcon aria-label="Bold">
    <SvgIcon iconName="bold" />
  </ToggleButtonGroup.Button>
  <ToggleButtonGroup.Button value="italic" withLoneIcon aria-label="Italic">
    <SvgIcon iconName="italic" />
  </ToggleButtonGroup.Button>
  <ToggleButtonGroup.Button
    value="underline"
    withLoneIcon
    aria-label="Underline"
  >
    <SvgIcon iconName="underline" />
  </ToggleButtonGroup.Button>
</ToggleButtonGroup.Root>
```

### Controlled toggle button group

As with many of our components, you can make the `ToggleButtonGroup` controlled, by passing your own state to `value` prop.
`onValueChange` handler is called when the state of the toggle group changes, allowing you to sync state.

```jsx
() => {
  const [value, setValue] = React.useState('active');

  return (
    <ToggleButtonGroup.Root
      type="single"
      aria-label="Filter options"
      variant="outline"
      value={value}
      onValueChange={setValue}
    >
      <ToggleButtonGroup.Button value="active">
        {'Active'}
      </ToggleButtonGroup.Button>
      <ToggleButtonGroup.Button value="inactive">
        {'Inactive'}
      </ToggleButtonGroup.Button>
      <ToggleButtonGroup.Button value="all">{'All'}</ToggleButtonGroup.Button>
    </ToggleButtonGroup.Root>
  );
};
```

---

## Accessibility features

<ul>
  <li iconName="check">

`ButtonGroup.Root` adds `role="group"` to convey that the buttons are part of a group to users of assistive technologies.

  </li>
  <li iconName="check">

`ButtonGroup.Button` with `isActive` prop set to `true` adds `aria-current` attribute to communicate currently active item to users of assistive technologies.

  </li>
  <li iconName="check">

`ToggleButtonGroup.Root` provides deep keyboard support via [Roving Focus Group utility](/components/utility/roving-focus-group). Focus movement is managed using [roving focus technique](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#x6-6-keyboard-navigation-inside-components).

  </li>
  <li iconName="check">

`ToggleButtonGroup.Button` uses `role="radio"` or `role="checkbox"` and keeps track of `aria-checked` attribute.

  </li>
</ul>

---

## API Reference

### ButtonGroup.Root

| Name          | Type                         | Default        | Description                                                                                                                                                                                                                                  | Required |
| ------------- | ---------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`         | `StitchesCss`                |                | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants. |          |
| `isDisabled`  | `boolean`                    |                | When `true`, entire button group will be disabled, preventing the user from interacting with it.                                                                                                                                             |          |
| `variant`     | `"strong" \| "outline"`      | `"outline"`    | Shared visual variant of the grouped buttons.                                                                                                                                                                                                |          |
| `size`        | `"medium" \| "small"`        |                | Shared size of the grouped buttons.                                                                                                                                                                                                          |          |
| `layout`      | `"inline" \| "stretch"`      |                | Defines how the group sizes itself and the buttons.                                                                                                                                                                                          |          |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Defines if the group should display buttons in a horizontal row (default) or stacked.                                                                                                                                                        |          |

### ButtonGroup.Button

<Callout variant="tip">

In addition to the props below, you can pass [Button props](/components/button#api-reference) with exception of `size`.

</Callout>

| Name         | Type                                                      | Default  | Description                                                                                                                                                                                                                                                                                  | Required |
| ------------ | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`         | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `button` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`        | `StitchesCss`                                             |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `isActive`   | `string`                                                  | `false`  | When `true`, the button will be highlighted as active.                                                                                                                                                                                                                                       |          |
| `isDisabled` | `boolean`                                                 | `false`  | When `true`, the button will be disabled, preventing the user from interacting with it.                                                                                                                                                                                                      |          |

### ToggleButtonGroup.Root

<Callout variant="tip">

In addition to the props below, you can pass [ButtonGroup props](#buttongroup).

</Callout>

| Name            | Type                        | Default | Description                                                                                                                                        | Required |
| --------------- | --------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `type`          | `"single" \| "multiple"`    |         | Determines whether a single option or multiple options of the group may be selected.                                                               | Yes      |
| `value`         | `string`                    |         | The controlled value of the selected item when `type` is `single`. Use in conjunction with `onValueChange`.                                        |          |
| `defaultValue`  | `string`                    |         | The value of the item to show as selected when first rendered and `type` is `single`. Use when you do not need to control the selection state.     |          |
| `onValueChange` | `(value: string) => void`   |         | Event handler called when the selection state changes and `type` is `single`.                                                                      |          |
| `value`         | `string[]`                  |         | The controlled value of the selected items when `type` is `multiple`. Use in conjunction with `onValueChange`.                                     |          |
| `defaultValue`  | `string[]`                  |         | The values of the items to show as selected when first rendered and `type` is `multiple`. Use when you do not need to control the selection state. |          |
| `onValueChange` | `(value: string[]) => void` |         | Event handler called when the selection state changes and `type` is `multiple`.                                                                    |          |
| `aria-label`    | `string`                    |         | Used to provide a better description of the toggle group for assistive tech users.                                                                 | Yes      |

### ToggleButtonGroup.Button

<Callout variant="tip">

In addition to the props below, you can pass [Button props](/components/button#api-reference) with exception of `size`.

</Callout>

| Name         | Type                                                      | Default  | Description                                                                                                                                                                                                                                                                                  | Required |
| ------------ | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`         | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `button` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`        | `StitchesCss`                                             |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `value`      | `string`                                                  |          | A unique value for the button.                                                                                                                                                                                                                                                               | Yes      |
| `isDisabled` | `boolean`                                                 | `false`  | When `true`, the button will be disabled, preventing the user from interacting with it.                                                                                                                                                                                                      |          |
