Button Group
A row (or column) of related buttons that should be visually grouped — toolbars, segmented controls, filter pills. Composes existing Button sizes and states. Use Secondary, Tertiary, or Ghost as the base variant; let the selected button carry the emphasis (primary fill via aria-pressed, or solid border via .btn-group-active-border).
When to use
- Use when 2–5 related actions share the same context (Bold / Italic / Underline, filter pills)
- Use Tertiary as the base variant for all buttons in a group — it reads as neutral and equal weight
- Use Primary only for the active / selected button within the group
- Use Attached variant when actions form a single logical control (segmented selector)
- Use Separated variant when actions are related but independently triggerable
- Keep all buttons in a group the same size
- Use Secondary or Ghost inside a group — Tertiary is the correct neutral base
- Use more than one Primary button in the same group — only one button should be active at a time
- Use for page-level navigation — use Tabs or sidebar Links instead
- Mix variants inside a group (e.g. Primary next to Tertiary for non-active buttons)
- Use more than 5 buttons in a single group — use a Dropdown instead
DigiLawyer Patterns
Button Group composes entirely with Button — all Button DigiLawyer Patterns carry over. The most relevant one for groups is shown below.
.btn-square. Never two icons inside a single button within the group.Anatomy
A Button Group wraps two or more Button atoms. The wrapper controls spacing and border-radius; individual buttons remain structurally unchanged.
- 1Group wrapper —
.btn-group. Setsdisplay: inline-flexand manages the gap or border-overlap between children. - 2Left button —
.btn-pos-left. Rounds left corners only. - 3Middle button(s) —
.btn-pos-middle. No border-radius on any corner. - 4Right button —
.btn-pos-right. Rounds right corners only. - 5Active indicator — Optional.
.btn-group-active-borderon the wrapper shows a coloured left border on the selected button.
Default
Wrap related buttons in a .btn-group. Adjacent buttons share borders so the row reads as a single component. Use this for segmented controls.
<div class="btn-group"> <button class="btn btn-tertiary btn-md"><span class="btn-label">Day</span></button> <button class="btn btn-tertiary btn-md"><span class="btn-label">Week</span></button> <button class="btn btn-tertiary btn-md"><span class="btn-label">Month</span></button> <button class="btn btn-tertiary btn-md"><span class="btn-label">Year</span></button> </div>
Attached vs separated
.btn-group is attached by default (shared borders). Add .btn-group-separated for a gap-spaced group where each button keeps its own radius — use this when buttons are unrelated peers (action bars, multi-action toolbars).
<!-- Attached --> <div class="btn-group">...</div> <!-- Separated --> <div class="btn-group btn-group-separated">...</div>
Sizes
Use a single size class on every button in the group. Mixing sizes inside a group is not supported.
With icons
Icon-only and icon+label work inside groups. Icon-only buttons are common for toolbars (alignment, formatting). The standard <span class="icon"> wrapper auto-sizes per button size.
Toggle / selection
For segmented controls where exactly one button is selected at a time, set aria-pressed="true" on the selected button (or class="active" if you don't need the semantics). Click any button below — only one stays selected.
<div class="btn-group" role="group" aria-label="View"> <button class="btn btn-tertiary btn-md" aria-pressed="false">...</button> <button class="btn btn-tertiary btn-md" aria-pressed="true">...</button> <button class="btn btn-tertiary btn-md" aria-pressed="false">...</button> </div> // Every .btn-group on the page toggles by default — add data-no-toggle to opt out. document.querySelectorAll('.btn-group:not([data-no-toggle]) .btn').forEach(b => { b.addEventListener('click', () => { b.closest('.btn-group') .querySelectorAll('.btn') .forEach(x => x.setAttribute('aria-pressed', x === b ? 'true' : 'false')); }); });
Vertical
Add .btn-group-vertical for a stacked column — useful in narrow sidebars or mobile layouts. Combines with .btn-group-separated.
States
Each button keeps its own disabled state. Disable an entire group by disabling all of its buttons, or a single button to indicate one option is unavailable.
Full matrix
A button-group's structure is defined by position: which corners are rounded and which borders collapse into the neighbouring button. The five position variants below are the building blocks — horizontal groups use Left / Middle / Right, vertical groups use Up / Middle / Down. Inside a real .btn-group these are applied automatically via :first-child / :last-child. The standalone .btn-pos-* helpers below let you visualise or hand-compose the same shapes.
Accessibility
Follows the WAI-ARIA Toolbar pattern for action groups, or the Radio Group pattern for selection groups.
| Attribute / Behaviour | Value | Notes |
|---|---|---|
| Wrapper role — toolbar | role="toolbar" | Use when buttons are independent actions (Bold, Italic, Copy) |
| Wrapper role — selection | role="group" | Use when buttons form a mutually exclusive selection (Day / Week / Month) |
| Selected state | aria-pressed="true" | Set on the active button for toggle/selection groups |
| Keyboard — focus | Tab | Each button is individually focusable |
| Keyboard — activate | Enter / Space | Activates the focused button |
| Icon-only buttons | aria-label required | Each icon-only button must have a descriptive aria-label |
API
| Class | On | Description |
|---|---|---|
| .btn-group | wrapper | Attached horizontal group — adjacent buttons share borders. Default. |
| .btn-group-separated | wrapper | Modifier — adds --btn-group-gap between buttons, restores per-button radius. |
| .btn-group-vertical | wrapper | Modifier — stacks buttons vertically. Combines with .btn-group-separated. |
| .btn-group-active-border | wrapper | Modifier — selected button adopts the .btn-active-border solid-border look instead of the primary fill. Use on a Tertiary base. |
| data-no-toggle | wrapper | Opt out of the default click-to-toggle behaviour. Every .btn-group toggles by default. |
| .btn-pos-left / -middle / -right | button | Position helpers for horizontal groups — corner radius + collapse the border that meets the neighbour. Applied automatically inside .btn-group; use explicitly only for hand-composed layouts or documentation. |
| .btn-pos-up / -down | button | Position helpers for vertical groups — top/bottom corner radius + collapse the meeting border. |
| role="group" | wrapper | Recommended ARIA role. Pair with aria-label. |
| aria-pressed | button | Selected state for toggle/segmented controls. Styling matches .active. |
| .active | button | CSS-only selected state — use when you don't need the ARIA semantics. |
| disabled | button | HTML attribute — disables one or more buttons in the group. |