Skip to content

ToggleButtonGroup ​

A toggle button group is a set of ToggleButtons that share a selection: one alignment out of three, or any combination of bold, italic and underline. Where the buttons fire actions rather than holding a state, you want a ButtonGroup.

ts
import { ToggleButton, ToggleButtonGroup, ToggleButtonGroupSeparator } from "ropav";

Every button in the group needs an id, because that is the key the selection is carried in.

selectionMode
size
orientation
template
<ToggleButtonGroup aria-label="Text style" :default-selected-keys='["bold"]'>
  <ToggleButton id="bold">Bold</ToggleButton>
  <ToggleButton id="italic">
    <ToggleButtonGroupSeparator />
    Italic
  </ToggleButton>
</ToggleButtonGroup>

One or many ​

selection-mode is the whole difference between the two shapes this component takes. Left at single it behaves like a set of radio buttons drawn as a control; at multiple each button is independent and the group is a row of switches. disallow-empty-selection keeps at least one pressed, which is what you want where the group always describes some state — text is aligned somehow, even if the reader has not chosen.

toggle-button-group-selection.vue
vue
<script setup lang="ts">
import { ToggleButton, ToggleButtonGroup, ToggleButtonGroupSeparator } from "ropav";

const alignments = [
  { id: "left", label: "Left" },
  { id: "center", label: "Centre" },
  { id: "right", label: "Right" },
] as const;

const styles = [
  { id: "bold", label: "Bold" },
  { id: "italic", label: "Italic" },
] as const;
</script>

<template>
  <div class="stack">
    <ToggleButtonGroup
      aria-label="Alignment"
      :default-selected-keys="['left']"
      disallow-empty-selection
    >
      <template v-for="(item, index) in alignments" :key="item.id">
        <ToggleButton :id="item.id">
          <ToggleButtonGroupSeparator v-if="index > 0" />
          {{ item.label }}
        </ToggleButton>
      </template>
    </ToggleButtonGroup>

    <ToggleButtonGroup aria-label="Text style" selection-mode="multiple">
      <template v-for="(item, index) in styles" :key="item.id">
        <ToggleButton :id="item.id">
          <ToggleButtonGroupSeparator v-if="index > 0" />
          {{ item.label }}
        </ToggleButton>
      </template>
    </ToggleButtonGroup>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  flex-direction: column;
  gap: calc(var(--rp-spacing) * 6);
}
</style>

v-model:selected-keys hands the selection to the caller; default-selected-keys just starts it somewhere. is-detached separates the buttons visually instead of joining them, for a group that should read as several controls that happen to agree.

Accessibility ​

  • Each button keeps aria-pressed, so a screen reader announces the state of the one it is on rather than the group's selection as a whole.
  • The group needs an aria-label. "Text style" tells a reader what the pressed buttons are about; without it they hear three unrelated toggles.
  • ToggleButtonGroupSeparator is decorative and aria-hidden — it goes inside the button that follows it, the same as in a button group, so the rule travels with the button.
  • Single selection here is not a radio group. Where the choice is a form value with a name and a validation state, use a RadioGroup and let this component be the toolbar control it looks like.

API ​

ToggleButtonGroup

PropTypeDefaultDescription
defaultSelectedKeysIterable<ToggleGroupKey>—Selected keys in uncontrolled mode.
disallowEmptySelectionboolean—Keeps at least one key selected, so the group can never be turned fully off.
fullWidthboolean—Stretches the group to the full width of its container.
isDetachedbooleanfalseSeparates the buttons visually instead of joining them into one control.
isDisabledboolean—Disables every button in the group.
orientation"horizontal" | "vertical""horizontal"Direction the buttons are laid out in. Falls back to the axis of an enclosing Toolbar.
selectedKeysIterable<ToggleGroupKey>—Selected keys in controlled mode.
selectionMode"single" | "multiple""single"Whether one or many buttons can be selected at a time.
size"xs" | "sm" | "md" | "lg"—Size for every button in the group. Each button can still set its own.

Slots: default.

EventPayload
selectionChangeSet<ToggleGroupKey>

ToggleButtonGroupSeparator

ToggleButtonGroupSeparator takes nothing but class.