ButtonGroup
A button group consists of a set of two or more normal buttons. Buttons in such a group signal a number of equally important actions that will occur when the user taps on them.
Guidelines
Using button groups
Each button within the button group must have a label. For icon-only buttons, the label will be visually hidden and available only to users of assistive technology.
Use the ButtonGroup component when you want users to choose actions from a set of actions, with the restriction that only one can be active at a time. If you want to enable users to select one or multiple options from a set of options, use ToggleButtonGroup instead.
Specifications
A button group consists of normal (framed) buttons, which may include the following elements:
- Icon (optional)
Icons simplify user recognition and provide the ability to shorten button labels to a minimum. - Label
Button labels should be as short as possible, with text that clearly states what action will be taken once the button is pressed (e.g. download, submit form, search).
Refer to the ButtonGroup component in Codex Figma.
Interaction states
Button groups have the following visually separate states:
- Default buttons
- Hover on one button
- Active button
- Focus on one button
- Disabled button
- Disabled button group
Demos
Open up the browser console to see events emitted on click.
Basic usage
Describe the buttons in the group with an array of ButtonGroupItem
objects. The text in the label
property will be displayed in the buttons. When a button is clicked, a click
event will be emitted with the value
property of the clicked button. Values must be unique within a button group.
If the label
property is omitted, the value
property will be used as the label. This allows using { value: 'Foo' }
as a shorthand for { label: 'Foo', value: 'Foo' }
.
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
/>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
export default defineComponent( {
name: 'BasicButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' },
{ value: 3, label: 'Three' },
{ value: 4, label: 'Four' },
{ value: 5, label: 'Five' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
></cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
// @vue/component
module.exports = defineComponent( {
name: 'BasicButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' },
{ value: 3, label: 'Three' },
{ value: 4, label: 'Four' },
{ value: 5, label: 'Five' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Name | Value |
---|---|
View | |
Reading direction |
With icons
Use the icon
property to add an icon before the text of a button. Use the disabled
property to disable individual buttons.
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
/>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
import { cdxIconEdit, cdxIconSpeechBubble, cdxIconCheck, cdxIconDownload, cdxIconTrash } from '@wikimedia/codex-icons';
export default defineComponent( {
name: 'ButtonGroupWithIcons',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 'edit', label: 'Edit', icon: cdxIconEdit },
{ value: 'talk', label: 'Discuss', icon: cdxIconSpeechBubble },
{ value: 'save', label: 'Done', icon: cdxIconCheck, disabled: true },
{ value: 'download', label: 'Download', icon: cdxIconDownload, disabled: true },
{ value: 'delete', label: 'Delete', icon: cdxIconTrash }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
></cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
const { cdxIconEdit, cdxIconSpeechBubble, cdxIconCheck, cdxIconDownload, cdxIconTrash } = require( './icons.json' );
// @vue/component
module.exports = defineComponent( {
name: 'ButtonGroupWithIcons',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 'edit', label: 'Edit', icon: cdxIconEdit },
{ value: 'talk', label: 'Discuss', icon: cdxIconSpeechBubble },
{ value: 'save', label: 'Done', icon: cdxIconCheck, disabled: true },
{ value: 'download', label: 'Download', icon: cdxIconDownload, disabled: true },
{ value: 'delete', label: 'Delete', icon: cdxIconTrash }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Icon-only buttons
To display an icon as the only content of a button, use the icon
property to specify an icon, and set the label
property to null
.
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
/>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
import { cdxIconEdit, cdxIconSpeechBubble, cdxIconCheck, cdxIconDownload, cdxIconTrash } from '@wikimedia/codex-icons';
export default defineComponent( {
name: 'IconOnlyButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 'edit', label: null, icon: cdxIconEdit, ariaLabel: 'Edit' },
{ value: 'talk', label: null, icon: cdxIconSpeechBubble, ariaLabel: 'Discuss' },
{ value: 'save', label: null, icon: cdxIconCheck, ariaLabel: 'Done', disabled: true },
{ value: 'download', label: null, icon: cdxIconDownload, ariaLabel: 'Download', disabled: true },
{ value: 'delete', label: null, icon: cdxIconTrash, ariaLabel: 'Delete' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
></cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
const { cdxIconEdit, cdxIconSpeechBubble, cdxIconCheck, cdxIconDownload, cdxIconTrash } = require( './icons.json' );
// @vue/component
module.exports = defineComponent( {
name: 'IconOnlyButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 'edit', label: null, icon: cdxIconEdit, ariaLabel: 'Edit' },
{ value: 'talk', label: null, icon: cdxIconSpeechBubble, ariaLabel: 'Discuss' },
{ value: 'save', label: null, icon: cdxIconCheck, ariaLabel: 'Done', disabled: true },
{ value: 'download', label: null, icon: cdxIconDownload, ariaLabel: 'Download', disabled: true },
{ value: 'delete', label: null, icon: cdxIconTrash, ariaLabel: 'Delete' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Disabled
The entire component can be disabled by setting the disabled
prop. Individual buttons can be disabled by setting their .disabled
property. Clicking a disabled button does not emit a click
event.
<template>
<cdx-button-group
:buttons="buttons"
:disabled="true"
@click="onClick"
/>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
export default defineComponent( {
name: 'DisabledButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' },
{ value: 3, label: 'Three' },
{ value: 4, label: 'Four', disabled: true },
{ value: 5, label: 'Five' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
:disabled="true"
@click="onClick"
></cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
// @vue/component
module.exports = defineComponent( {
name: 'DisabledButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' },
{ value: 3, label: 'Three' },
{ value: 4, label: 'Four', disabled: true },
{ value: 5, label: 'Five' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Overflowing buttons
When the button group is too large to fit on one line, the buttons overflow to the next line.
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
/>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
export default defineComponent( {
name: 'MaximumButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'First button' },
{ value: 2, label: 'Second button' },
{ value: 3, label: 'Third button with a long label' },
{ value: 4, label: 'Fourth button with a long label' },
{ value: 5, label: 'Fifth button' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
></cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
// @vue/component
module.exports = defineComponent( {
name: 'MaximumButtonGroup',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'First button' },
{ value: 2, label: 'Second button' },
{ value: 3, label: 'Third button with a long label' },
{ value: 4, label: 'Fourth button with a long label' },
{ value: 5, label: 'Fifth button' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Custom button display
The contents of the buttons can be customized using the default slot. The ButtonGroupItem
object for each button is available through the button
binding. In this example, the value of the button is displayed in superscript after its label.
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
>
<template #default="{ button }">
{{ button.label }}
<sup>
({{ button.value }})
</sup>
</template>
</cdx-button-group>
</template>
<script>
import { defineComponent } from 'vue';
import { CdxButtonGroup } from '@wikimedia/codex';
export default defineComponent( {
name: 'ButtonGroupWithSlot',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
<template>
<cdx-button-group
:buttons="buttons"
@click="onClick"
>
<template #default="{ button }">
{{ button.label }}
<sup>
({{ button.value }})
</sup>
</template>
</cdx-button-group>
</template>
<script>
const { defineComponent } = require( 'vue' );
const { CdxButtonGroup } = require( '@wikimedia/codex' );
// @vue/component
module.exports = defineComponent( {
name: 'ButtonGroupWithSlot',
components: {
CdxButtonGroup
},
setup() {
const buttons = [
{ value: 1, label: 'One' },
{ value: 2, label: 'Two' }
];
function onClick( value ) {
// eslint-disable-next-line no-console
console.log( 'click event emitted with value:', value );
}
return {
buttons,
onClick
};
}
} );
</script>
Vue usage
Props
Prop name | Description | Type | Default |
---|---|---|---|
buttons (required) | Objects describing the buttons in the group. See the ButtonGroupItem type. | ButtonGroupItem[] | |
disabled | Whether the entire group is disabled. If this is set to true, all buttons in the group are disabled. Buttons can also be disabled individually by setting their disabled property to true. | boolean | false |
Events
Event name | Properties | Description |
---|---|---|
click | value string|number - The value property of the button that was clicked | Emitted when a button is clicked |
Slots
Name | Description | Bindings |
---|---|---|
default | Content of an individual button | button ButtonGroupItem - Object describing the button to display |