Button group & split
Two shapes under one class. Attached, the segments share edges and read as a single control - use it for a set of mutually exclusive choices. Detached, it is a plain row of related but independent actions. A split button is the same shape with a menu on the end. For a set of choices that has to SUBMIT, see Segmented on the Field page: these are buttons, and buttons carry no value.
Reference
sk-button-group
Direct children must be sk-button. The shared 1px border is collapsed with a negative margin rather than removed, so a hovered or focused segment keeps its whole outline instead of showing a clipped focus ring.
<div class="sk-button-group" role="group" aria-label="View">
<button class="sk-button" data-variant="neutral" aria-pressed="true">Grid</button>
<button class="sk-button" data-variant="neutral" aria-pressed="false">List</button>
</div>| Attribute | Type | Default | Notes |
|---|---|---|---|
data-attached | "false" | attached | Omit for the segmented shape. Set to "false" for a spaced row of independent actions. |
data-orientation | "vertical" | horizontal | Stacks the segments and moves the rounded corners to top and bottom. |
role | "group" | "group" | Set by the binding. |
aria-label | string | - | Name the choice, not the options. Without it a segmented control is announced as a bare list of buttons. |
sk-button[aria-pressed]
The selected segment. Driven by aria-pressed so the visual state and the announced state are the same attribute - there is no separate .is-active class to fall out of sync.
<button class="sk-button" aria-pressed="true">Selected</button>sk-split
One primary action with its variants behind a menu. Built on the group's shape - same joined corners, same collapsed border, same z-index on focus so a ring is never clipped - and adds one thing: the seam between two SOLID buttons, drawn as an inset rule in currentColor at low alpha so it works on every variant. Without it the pair looks like one very wide button that mysteriously responds to a click on its right-hand quarter.
<div class="sk-split">
<button class="sk-button">Deploy</button>
<button class="sk-button" popovertarget="deploy-menu"
aria-label="More deploy options">…</button>
</div>
<div class="sk-menu" id="deploy-menu" popover>…</div>| Attribute | Type | Default | Notes |
|---|---|---|---|
aria-label | string | - | On the toggle, and it matters more here than almost anywhere else: a primary button followed by an unnamed one is announced as "Deploy, button, button". Name it after what it opens - never "Menu" or "Toggle". |
> .sk-button:last-child | - | - | The toggle is matched structurally rather than by a class: a binding cannot add a class through an attribute pass-through without emitting a second class attribute, which the browser resolves by keeping the first and dropping the rest. |
Examples
Split button
The common action stays one click away while its rarer siblings stop competing for room in the toolbar. Tab to the second half: it has a name of its own, because "Deploy, button, button" tells the reader nothing.
Show markup
<div class="sk-flex sk-flex-wrap sk-items-center sk-gap-4">
<div class="sk-split">
<button class="sk-button" type="button" data-variant="solid" data-size="md">
Deploy
</button>
<button class="sk-button" type="button" data-variant="solid" data-size="md" aria-label="More deploy options" popovertarget="split-deploy">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
</div>
<div class="sk-menu" id="split-deploy" popover aria-label="Deploy options">
<button type="button" class="sk-menu-item">
Deploy to production
<span class="sk-menu-item-detail">
<kbd class="sk-kbd">
Ctrl
</kbd>
<kbd class="sk-kbd">
D
</kbd>
</span>
</button>
<button type="button" class="sk-menu-item">
Deploy to staging
</button>
<button type="button" class="sk-menu-item">
Deploy a specific build…
</button>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger">
Roll back
</button>
</div>
<div class="sk-split">
<button class="sk-button" type="button" data-variant="neutral" data-size="sm">
Export CSV
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="sm" aria-label="More export formats" popovertarget="split-export">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
</div>
<div class="sk-menu" id="split-export" popover aria-label="Export formats">
<button type="button" class="sk-menu-item">
Export JSON
</button>
<button type="button" class="sk-menu-item">
Export XLSX
</button>
</div>
</div>Segmented control
The attached default. One segment is pressed; the group carries the accessible name.
Show markup
<div class="sk-flex sk-flex-col sk-gap-4">
<div class="sk-button-group" role="group" aria-label="View">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="true">
Grid
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
List
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Table
</button>
</div>
<div class="sk-button-group" role="group" aria-label="Range">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Day
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="true">
Week
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Month
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Year
</button>
</div>
</div>Sizes
Corner radius follows the size variant rather than being hardcoded, so a small group keeps the smaller corner.
Show markup
<div class="sk-flex sk-flex-col sk-items-start sk-gap-4">
<div class="sk-button-group" role="group" aria-label="Alignment">
<button class="sk-button" type="button" data-variant="neutral" data-size="sm" aria-pressed="true">
Left
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="sm" aria-pressed="false">
Centre
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="sm" aria-pressed="false">
Right
</button>
</div>
<div class="sk-button-group" role="group" aria-label="Alignment">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="true">
Left
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Centre
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Right
</button>
</div>
<div class="sk-button-group" role="group" aria-label="Alignment">
<button class="sk-button" type="button" data-variant="neutral" data-size="lg" aria-pressed="true">
Left
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="lg" aria-pressed="false">
Centre
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="lg" aria-pressed="false">
Right
</button>
</div>
</div>Detached
For a form's action row, where the buttons are independent rather than mutually exclusive.
Show markup
<div class="sk-button-group" role="group" data-attached="false">
<button class="sk-button" type="submit" data-variant="solid" data-size="md">
Save
</button>
<button class="sk-button" type="button" data-variant="quiet" data-size="md">
Cancel
</button>
</div>Vertical
Show markup
<div class="sk-button-group" role="group" aria-label="Sort" data-orientation="vertical">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="true">
Newest first
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Oldest first
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md" aria-pressed="false">
Alphabetical
</button>
</div>Mixed variants
Segments keep their own variant, so a destructive option can sit in an otherwise neutral group.
Show markup
<div class="sk-button-group" role="group" aria-label="Record actions">
<button class="sk-button" type="button" data-variant="neutral" data-size="md">
Edit
</button>
<button class="sk-button" type="button" data-variant="neutral" data-size="md">
Duplicate
</button>
<button class="sk-button" type="button" data-variant="danger" data-size="md">
Delete
</button>
</div>