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.
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.from({ length: 12 }, (_, index) => (
<IconButton key={index} label={`Item #${index}`}>
<SvgPlaceholder />
</IconButton>
));
return (
<div className='demo-container'>
<ButtonGroup
overflowButton={(overflowStart) => (
<DropdownMenu
menuItems={(close) =>
Array(buttons.length - overflowStart)
.fill(null)
.map((_, _index) => {
const index = overflowStart + _index;
return (
<MenuItem
key={index}
onClick={close}
startIcon={<SvgPlaceholder />}
>
Item #{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'
readOnly
/>
<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<...> |