Segmented button

Deprecated (DECISIONS D4): the segmented button (.m3e-segmented-button, SingleChoiceSegmentedButtonRow, MultiChoiceSegmentedButtonRow) ships until 2.0 for migration and gets no new features; React warns once in development. Use the connected button group. m3.material.io recommends it instead since the M3 Expressive update: .m3e-button-group--connected, <ButtonGroup variant="connected" selectionMode="single | multiple">.

Segmented buttons (COMPONENT_SPEC §37; Compose SingleChoiceSegmentedButtonRow / MultiChoiceSegmentedButtonRow with SegmentedButton) on native inputs: radios for a single choice in a role="radiogroup", checkboxes for several in a role="group". The buttons share the widest one's width and overlap by their 1dp outline; the row is 48dp high for the touch targets, the 40dp buttons centered in it. Selecting scales the check in from its bottom corner on the fast spatial spring while the label slides aside; unselecting removes the check at once and slides the label back. No JavaScript is needed: arrow keys move a single choice and wrap (WebKit stops at the ends), Tab enters at the selected button, Space selects or toggles.

Static (m3e-css)

A .m3e-segmented-button-row of <label class="m3e-segmented-button">s around the __input, the __icon slot (the check icon, then an optional icon shown while unselected) and the __label. The first button takes the full corners on its start side, the last on its end side. The ripple needs @kyralabs/m3e-elements/ripple.js (this section uses attachAutoRipple).

Range

Filters

Notifications

Disabled range

Size

Alone

Right to left

Element

There is no <m3e-segmented-button> (owner decision M9 #29): native radios and checkboxes already select, take part in forms and handle the keyboard, so the plain markup above is the element-layer API. Load @kyralabs/m3e-elements/ripple.js for the press ripple.

React

<SingleChoiceSegmentedButtonRow value defaultValue onChange isDisabled name aria-label> (React Aria useRadioGroup) or <MultiChoiceSegmentedButtonRow value defaultValue onChange isDisabled> (useCheckboxGroup) around <SegmentedButton value icon isDisabled>; the same DOM as the static markup. Below, Compose's two samples and a checkbox that disables both rows.

Sources

androidx Compose Material3 1.5.0-beta01 (19991f2c): OutlinedSegmentedButtonTokens.kt as read by SegmentedButton.kt (defaultSegmentedButtonColors L548–572, ContentPadding L617–623, CheckedZIndexFactor L852, IconSpacing L853, the rows L327–380, itemShape L597–611, the content L383–457, the icon motion L644–673; only the hidden overloads L253–311 are @Deprecated upstream), Surface.kt (L335–410, L470–564), Button.kt (ButtonDefaults.MinWidth / MinHeight, L1053–1065) and SegmentedButtonSamples.kt; values in components/segmented-button-defaults.css (lines in PARITY.md).

m3.material.io Segmented buttons (page 409b50be-403a-4846-932c-706a9b2137dd: no longer recommended since May 2025, use the connected button group). DECISIONS D4 (shipped deprecated until 2.0) and D20 (10) (Enter does not select); SOURCES register #54.