Skip to content
SuperCoach

Components · Actions

Button group

Beta

Groups related buttons, such as Previous and Next week.

Week 4 of 12

When to use

  • To join two to four related actions that act on the same thing: Previous week and Next week, Edit and Duplicate on a program.
  • For a split button: a main action with a menu of other ways to do it ("Send check-in" plus "Schedule for later").
  • To attach a button to a field, such as a search box with its search button.

When not to use

  • To choose between options that stay selected (kg or lb, list or cards): use a Toggle group. A button group only starts actions.
  • For more than four actions, or actions of mixed importance: show the primary Button and put the rest in a Dropdown menu.
  • For a form's Save and Cancel: those are separate buttons with a gap, not a group, so the primary action stands out.

Anatomy

Week 4 of 12
  1. 1. Group: a row (or column) with role="group"; inner corners are squared and shared borders collapse
  2. 2. Button: any Button variant, usually outline
  3. 3. Text segment (optional): ButtonGroupText, a non-interactive label such as the current week

Variants

Horizontal

Vertical

Split button, with separator

With an input

VariantUse for
horizontal (default)Most groups: week navigation, program actions in a card header.
verticalNarrow columns, such as moving an exercise up or down in a workout.
With ButtonGroupSeparatorFilled buttons (secondary, default) that have no border of their own, so the split shows. Outline buttons don't need it.
With an inputA field and its action. The input grows to fill the group.

The group has no sizes of its own: give every button in it the same size. Nest groups (a ButtonGroup inside a ButtonGroup) to put a gap between sets of actions in one toolbar.

States

Week 12 of 12

States belong to each button; the group only makes sure the focused one is drawn on top of its neighbors.

StateWhat changesToken
HoverThe hovered button's own hover fillhover:bg-accent (outline)
Focus-visibleThe focused button is raised so its ring isn't hidden by the next buttonz-(--z-raised), ring-ring/50
DisabledOnly that button: half opacity, no pointer events. Keep it in place so the group doesn't jumpopacity-(--opacity-disabled)
Text segmentMuted fill, so it doesn't look clickablebg-muted

Usage guidelines

Do.Related actions on one program, all the same variant and size.
Don't.Mixed variants and a destructive action glued to Save. One slip deletes the program.
  • Keep a destructive action out of the group, or behind a confirmation in a menu.
  • Disable a button that can't act right now (Next week on the last week) instead of removing it.
  • Give the group an aria-label when its purpose isn't clear from the buttons alone.

Content guidelines

  • Short labels, verb first, sentence case: "Edit", "Duplicate", "Previous week".
  • Icon-only buttons are fine when the icons are well known (arrows, trash), but each needs an aria-label.
  • A text segment states where you are, with Western digits (Q22): "Week 4 of 12", "الأسبوع 4 من 12".

Accessibility

KeyDoes
Tab / Shift+TabMoves to the next or previous button; each button is its own tab stop
Enter or SpaceActivates the focused button
  • The group renders role="group". With an aria-label, a screen reader announces it on entry: "Program week, group, Previous week, button".
  • ButtonGroupText is plain text, not focusable, and is read in order between the buttons.
  • Arrow keys don't move between buttons. For a set of options with arrow-key navigation, use a Toggle group.
  • Coach primary buttons fail contrast today (DECISIONS #3).

RTL

  • The group's order follows the reading direction: "Previous week" is at the right in RTL. The squared and rounded corners use logical classes (rounded-s-none, rounded-e-none, border-s-0), so the outer corners stay rounded in both directions.
  • Directional icons in the buttons need rtl:-scale-x-100, as in the example: the "previous" chevron points right in RTL. A trash or copy icon doesn't mirror.
  • Vertical groups are the same in both directions.

Tokens used

Read from components/ui/button-group.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--inputbg-inputneutral-200neutral-200
--mutedbg-mutedneutral-100neutral-100
  • Layerz-(--z-raised)
  • Radiusrounded-e-md rounded-md
  • Radiusrounded-s-none rounded-e-none rounded-t-none rounded-b-none
  • Shadowshadow-xs
  • Typefont-medium
  • Typetext-sm

Props

<ButtonGroup>

Also takes every prop of <div>

ButtonGroup props
PropTypeDefault
orientation"horizontal" | "vertical""horizontal"

<ButtonGroupText>

Also takes every prop of <div>

ButtonGroupText props
PropTypeDefault
asChild?booleanfalse

<ButtonGroupSeparator>

Also takes every prop of <Separator>

No props of its own.

Replaces in coach-admin

From the read-only audit of coach-admin: 4 style values, 4 uses.

coach-admin has no shared button-group component. Buttons are placed side by side in one-off containers such as .selectWeekBtnContainer (the program week switcher), which also needs a separate margin fix in rtl.css. The logical classes here remove that fix.

Classes and selectors

  • .formBtnsContainer2
  • .selectWeekBtnContainer2

Button, Toggle group, Dropdown menu, Input.