Skip to content

Button group

Keep related controls together, such as a main action and its menu or a field and its submit button.

<script setup lang="ts">import { Archive, ArrowLeft, Clock, Ellipsis, Flag, Pencil, Trash2 } from '@lucide/vue'import { UiButtonGroup, UiIconButton, UiButton, UiMenu, UiListItem, UiConfirm, UiToaster, useConfirm } from 'grani' const { confirm } = useConfirm() const remove = () =>  confirm({    title: 'Delete the message?',    message: 'It is removed for everyone. This cannot be undone.',    confirmLabel: 'Delete',    tone: 'danger',  })</script> <template>  <UiButtonGroup ariaLabel="Message actions">    <UiButtonGroup ariaLabel="Back">      <UiIconButton :icon="ArrowLeft" ariaLabel="Back to the inbox" />    </UiButtonGroup>    <UiButtonGroup ariaLabel="Triage">      <UiButton variant="outline">        <Archive aria-hidden="true" />        Archive      </UiButton>      <UiButton variant="outline">        <Flag aria-hidden="true" />        Report      </UiButton>    </UiButtonGroup>    <UiButtonGroup ariaLabel="Snooze">      <UiButton variant="outline">        <Clock aria-hidden="true" />        Snooze      </UiButton>      <UiMenu align="end">        <template #trigger>          <UiIconButton :icon="Ellipsis" ariaLabel="More actions" />        </template>        <UiListItem as="button" title="Edit">          <template #media><Pencil /></template>        </UiListItem>        <UiListItem as="button" title="Delete" tone="danger" @click="remove">          <template #media><Trash2 /></template>        </UiListItem>      </UiMenu>    </UiButtonGroup>  </UiButtonGroup>  <!-- Once, at the app's root: leave out what the app has there already. -->  <UiConfirm />  <UiToaster /></template>

Also called segmented buttons, joined buttons, split button.

Usage

<UiButtonGroup>…</UiButtonGroup>

With GraniResolver in the Vite config, a template needs no import: set it up once.

API

Name · typeDefaultDescription
ariaLabelstringName of the group for a screen reader: "Pagination", "Period". Inside UiField group the legend names it.
orientationhorizontal | vertical= "horizontal""horizontal"Controls in a row or in a column.

Anything else lands on the root element: native attributes, aria-*, data-testid.

When to use another component

When you needTake
One choice among a fewRadio group segmented
A lone actionButton
The search and the filters over a listTable toolbar