action · conformant
ButtonGroup
ButtonGroupButtonGroupProps
import { Button, ButtonGroup, Icon, IconButton, Surface, Text } from '@language-lit/material3-expressive'
export function ButtonGroupExample() {
return (
<Surface
as="section"
aria-labelledby="button-group-example-title"
color="surface-container-low"
shape="extra-large"
className="button-group-example"
>
<Text as="h2" id="button-group-example-title" variant="titleLarge" emphasis="emphasized">
Button groups
</Text>
<Text as="p" variant="bodyMedium">
Arbitrary children arranged in a row. Press one to see it grow and
its neighbors compress, reading each child's own native :active
state via CSS :has() -- no JavaScript layout measurement.
</Text>
<div className="button-group-example__row">
<ButtonGroup aria-label="Text formatting">
<IconButton aria-label="Bold" variant="tonal">
<Icon source="format_bold" />
</IconButton>
<IconButton aria-label="Italic" variant="tonal">
<Icon source="format_italic" />
</IconButton>
<IconButton aria-label="Underline" variant="tonal">
<Icon source="format_underlined" />
</IconButton>
</ButtonGroup>
</div>
<div className="button-group-example__row">
<ButtonGroup aria-label="Actions">
<Button variant="outlined">One</Button>
<Button variant="outlined">Two</Button>
<Button variant="outlined">Three</Button>
<Button variant="outlined">Four</Button>
</ButtonGroup>
</div>
</Surface>
)
}ButtonGroup arranges Button/IconButton (or other interactive)
children in a horizontal row. Pressing one child visibly grows it and
compresses its immediate siblings — the Material 3 Expressive
"press-triggered neighbor compression" interaction.
import { Button, ButtonGroup } from '@language-lit/material3-expressive'
import '@language-lit/material3-expressive/styles.css'
<ButtonGroup aria-label="Text formatting">
<Button variant="tonal">Bold</Button>
<Button variant="tonal">Italic</Button>
<Button variant="tonal">Underline</Button>
</ButtonGroup>Contract
childrenare rendered directly in a flex row with the sourcedBetweenSpacegap — there is no data-driven item API; use whatever interactive elements you'd otherwise render (typicallyButton/IconButton).role="group"by default (override with an explicitrole, e.g."toolbar");aria-label/aria-labelledbyname the group as a whole. Every child keeps native tab order and its own accessible name.- Only the standard row treatment is covered. For a connected,
single/multi-select row of buttons, use
SegmentedButtonGroupinstead. - No automatic overflow into a dropdown menu — use
flex-wrapor your own responsive logic if children may not all fit.
Tokens and boundaries
Spacing and the press-compression scale come entirely from
--m3e-comp-button-group-* CSS custom properties, scoped by
Material3Provider. ButtonGroup injects no runtime styles and uses no
requestAnimationFrame loop — the compression interaction is a CSS
transform: scale() pair reading each child's own native :active state
via :has(), not a JavaScript layout measurement.