Components / Actions

ButtonGroup

Groups related controls horizontally or vertically without changing their behavior.

Preview

Use cases

Related commands

Visually join commands such as previous and next without changing their native button behavior.

Spaced group

Set attached to false when related actions need separate outlines.

Usage example

Vue
<script setup lang="ts">
import Button from './components/ui/button/Button.vue'
import ButtonGroup from './components/ui/button-group/ButtonGroup.vue'
</script>

<template>
  <ButtonGroup aria-label="Text alignment">
    <Button variant="outline">Left</Button>
    <Button variant="outline">Center</Button>
    <Button variant="outline">Right</Button>
  </ButtonGroup>
</template>

More examples

History navigation

Each button keeps its own disabled state.

History navigation
<script setup lang="ts">
import Button from './components/ui/button/Button.vue'
import ButtonGroup from './components/ui/button-group/ButtonGroup.vue'
defineProps<{ canUndo: boolean; canRedo: boolean }>()
</script>
<template>
  <ButtonGroup aria-label="History">
    <Button variant="outline" :disabled="!canUndo" @click="$emit('undo')">Undo</Button>
    <Button variant="outline" :disabled="!canRedo" @click="$emit('redo')">Redo</Button>
  </ButtonGroup>
</template>

Vertical actions

Orientation changes the visual stack, not the children’s behavior.

Vertical actions
<script setup lang="ts">
import Button from './components/ui/button/Button.vue'
import ButtonGroup from './components/ui/button-group/ButtonGroup.vue'
</script>
<template>
  <ButtonGroup orientation="vertical" :attached="false" aria-label="Export formats">
    <Button variant="outline" @click="$emit('export', 'pdf')">PDF</Button>
    <Button variant="outline" @click="$emit('export', 'csv')">CSV</Button>
  </ButtonGroup>
</template>

Key API

The most useful props, models, slots, events, and methods for this component.

Key API for ButtonGroup
NameTypeDefault or requirement
orientationhorizontal | verticalhorizontal
attachedbooleantrue
defaultslotrequired

The root has role="group". Name it with aria-label or aria-labelledby when nearby text does not already identify the group; each child retains its own keyboard, disabled, and form behavior.

Implementation notes

  • ButtonGroup provides role="group" and visual joins; it does not coordinate selection.
  • Set attached=false to retain space and independent corners between controls.

Accessibility and localization

  • Name the group when nearby text does not identify its purpose.
  • Every child remains an independent keyboard stop with its own action.
Weini UIDesign system · Vue component library · Free and public