Skip to Content

ButtonGroup

A button group is a set of buttons with similar functionality.

import * as React from 'react';
import { ButtonGroup, IconButton } from '@itwin/itwinui-react';
import {
  SvgAdd,
  SvgEdit,
  SvgDelete,
  SvgUndo,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <ButtonGroup>
      <IconButton onClick={() => {}} label='Add'>
        <SvgAdd />
      </IconButton>
      <IconButton onClick={() => {}} label='Edit' isActive>
        <SvgEdit />
      </IconButton>
      <IconButton disabled onClick={() => {}} label='Delete'>
        <SvgDelete />
      </IconButton>
      <IconButton onClick={() => {}} label='Undo'>
        <SvgUndo />
      </IconButton>
    </ButtonGroup>
  );
};

Use a button group if you want to put similar functionality in one place. It helps users differentiate functional areas of the UI.

Buttons in a button group can be active, disabled and both.

Usage

The ButtonGroup should almost always be used with IconButton components. Make sure to also pass the label prop to each IconButton; this text will be used to label the button and will be displayed in a tooltip.

<ButtonGroup>
<IconButton label="Add">
<SvgAdd>
</IconButton>
<IconButton label="Edit">
<SvgEdit>
</IconButton>
</ButtonGroup>

Toolbar

By default, the buttons are each considered to be separate tab stops. If you want to group them together in a single tab stop, you can enable the toolbar pattern by specifying role="toolbar". This will add all required behaviors for the toolbar pattern, including arrow-key navigation and focus management.

import * as React from 'react';
import { ButtonGroup, IconButton } from '@itwin/itwinui-react';
import {
  SvgAdd,
  SvgEdit,
  SvgDelete,
  SvgUndo,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <ButtonGroup role='toolbar'>
      <IconButton label='Add' onClick={() => {}}>
        <SvgAdd />
      </IconButton>
      <IconButton label='Edit' onClick={() => {}}>
        <SvgEdit />
      </IconButton>
      <IconButton label='Delete' disabled onClick={() => {}}>
        <SvgDelete />
      </IconButton>
      <IconButton label='Undo' onClick={() => {}}>
        <SvgUndo />
      </IconButton>
    </ButtonGroup>
  );
};

Note: role="toolbar" should only be used when the ButtonGroup contains buttons. Do not use it with inputs and other non-button elements.

Overflow

If there is not enough space to display all of the buttons, the buttons can truncate into an dropdown menu.

import * as React from 'react';
import {
  ButtonGroup,
  DropdownMenu,
  IconButton,
  MenuItem,
} from '@itwin/itwinui-react';
import { SvgMore, SvgPlaceholder } from '@itwin/itwinui-icons-react';

export default () => {
  const buttons = Array(12)
    .fill(null)
    .map((_, _index) => {
      return (
        <IconButton label='Placeholder'>
          <SvgPlaceholder />
        </IconButton>
      );
    });

  return (
    <div className='demo-container'>
      <ButtonGroup
        overflowButton={(overflowStart) => (
          <DropdownMenu
            menuItems={(close) =>
              Array(buttons.length - overflowStart + 1)
                .fill(null)
                .map((_, _index) => {
                  const index = overflowStart + _index;
                  const onClick = () => {
                    close();
                  };
                  return (
                    <MenuItem
                      key={index}
                      onClick={onClick}
                      startIcon={<SvgPlaceholder />}
                    >
                      Button #{index}
                    </MenuItem>
                  );
                })
            }
          >
            <IconButton label='More'>
              <SvgMore />
            </IconButton>
          </DropdownMenu>
        )}
      >
        {buttons}
      </ButtonGroup>
    </div>
  );
};

Vertical

Use the orientation prop to switch the button group to vertical.

import * as React from 'react';
import { ButtonGroup, IconButton } from '@itwin/itwinui-react';
import {
  SvgAdd,
  SvgEdit,
  SvgDelete,
  SvgUndo,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <ButtonGroup orientation='vertical'>
      <IconButton onClick={() => {}} label='Add'>
        <SvgAdd />
      </IconButton>
      <IconButton onClick={() => {}} label='Edit' isActive>
        <SvgEdit />
      </IconButton>
      <IconButton disabled onClick={() => {}} label='Delete'>
        <SvgDelete />
      </IconButton>
      <IconButton onClick={() => {}} label='Undo'>
        <SvgUndo />
      </IconButton>
    </ButtonGroup>
  );
};

With input

You can combine inputs with buttons in a button group. Use this pattern sparingly.

import * as React from 'react';
import { ButtonGroup, IconButton, Input, Button } from '@itwin/itwinui-react';
import { SvgSearch } from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <div className='demo-container'>
      <ButtonGroup>
        <Button>Button 1</Button>
        <Input aria-label='Search bar' />
        <IconButton label='Search'>
          <SvgSearch />
        </IconButton>
      </ButtonGroup>
      <ButtonGroup>
        <Input
          aria-label='URL'
          value='https://itwinui.bentley.com/docs/buttongroup'
        />
        <Button styleType='high-visibility'>Copy</Button>
      </ButtonGroup>
    </div>
  );
};

Usage guidelines

  • The button group should only consist of default buttons or borderless buttons.
  • Make sure to label IconButtons with the label prop.
  • You should not mix different styled buttons in the same group.
  • You can put buttons and button groups in close proximity. In such cases, see if there is a main action and give it emphasis with a high visibility button.
import * as React from 'react';
import { ButtonGroup, IconButton, Button } from '@itwin/itwinui-react';
import {
  SvgAdd,
  SvgEdit,
  SvgDelete,
  SvgUndo,
  SvgSearch,
  SvgFilter,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <div className='demo-container'>
      <Button styleType='high-visibility' startIcon={<SvgAdd />}>
        New
      </Button>
      <ButtonGroup>
        <IconButton label='Edit'>
          <SvgEdit />
        </IconButton>
        <IconButton disabled label='Delete'>
          <SvgDelete />
        </IconButton>
        <IconButton label='Undo'>
          <SvgUndo />
        </IconButton>
      </ButtonGroup>
      <div className='demo-spacer' />
      <ButtonGroup>
        <IconButton isActive label='Filter'>
          <SvgFilter />
        </IconButton>
        <IconButton label='Search'>
          <SvgSearch />
        </IconButton>
      </ButtonGroup>
    </div>
  );
};

Props

Prop Description Default
children
Buttons in the ButtonGroup.
ReactNode
overflowButton
If specified, this prop will be used to show a custom button when overflow happens, i.e. when there is not enough space to fit all the buttons.
Expects a function that takes the index of the first button that is overflowing (i.e. hidden) and returns the ReactNode to render.
The placement of this button can be controlled using the overflowPlacement prop.
(firstOverflowingIndex: number) => ReactNode
overflowPlacement
If overflowButton is specified, should it placed at the start or the end?
"end" | "start"
'end'
orientation
Should the buttons be placed in a horizontal or vertical layout?
"horizontal" | "vertical"
'horizontal'
role
ARIA role for the ButtonGroup.
If set to toolbar', it will automatically support arrow-key navigation.
Note: role="toolbar" should not be used when the ButtonGroup contains non-button elements (such as inputs).
"toolbar" | AnyString
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>