rc-segmented-button
Segmented button group backed by native radio inputs.
- Package
@rcarls/rc-segmented-button- Element
<rc-segmented-button>- Native dependency
- Direct-child fieldset with radio inputs
- State model
- Controlled or uncontrolled selected value
- Main events
rc-segmented-button-change- Related
- Usage rulesTheme previews
Installation
- npm
- Yarn
- pnpm
npm install @rcarls/rc-webcomponents@next
yarn add @rcarls/rc-webcomponents@next
pnpm add @rcarls/rc-webcomponents@next
import '@rcarls/rc-webcomponents/rc-segmented-button/define';
Usage
<rc-segmented-button>
<fieldset>
<legend>Text size</legend>
<label><input type="radio" name="size" value="small" /> Small</label>
<label><input type="radio" name="size" value="medium" checked /> Medium</label>
<label><input type="radio" name="size" value="large" /> Large</label>
</fieldset>
</rc-segmented-button>
The fieldset, legend, labels, and radios stay in light DOM for forms and no-JavaScript fallback.
Live demo
Accessibility
The fieldset and legend name the group, and each radio keeps its role, label, and checked state,
including while a theme hides the radio's visual box. Selection follows focus, as in a native
radio group, and fires change on the radio.
| Key | Action |
|---|---|
| Right Arrow, Down Arrow | Selects and focuses the next segment, wrapping to the first. |
| Left Arrow, Up Arrow | Selects and focuses the previous segment, wrapping to the last. |
| Home, End | Selects and focuses the first or last segment. |
Disabled segments are skipped. Left and Right swap in right-to-left text, and with
orientation="vertical" only Up and Down Arrow move. See the
WAI-ARIA Radio Group pattern.
In forced-colors mode the component restates the selected segment in system colors, so selection stays visible after the forced palette replaces whatever background a theme selects a segment with. Themes do not need to handle this, and a theme that omits the optional selected-icon slot is still covered.
Theming
Without a theme, the fieldset, legend, and radio controls retain their browser
appearance. Setting --rc-segmented-button-appearance: segmented turns on the
component's own recipe: a flat fieldset, a visually hidden legend, and radios
that stay focusable and in the accessibility tree while being invisible. The
packaged themes set it, so the semantic fieldset and legend remain available to
assistive technology while the labels read as segment surfaces.
That one switch is read with a CSS style container query, which has narrower support than the rest of this package: Chrome 111, Safari 18, and Firefox 128. The component's behavior, keyboard handling, and form participation are unaffected and work wherever custom elements do.
Where style queries are unsupported the recipe does not apply and the control falls back to the native fieldset and radio appearance. That fallback stays fully usable and accessible, but it looks like plain radio buttons rather than a segmented control. Write the segment layout in your own CSS if that is not acceptable for your audience.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
value | value | string | Not specified | Current selected radio value. Host writes are silent. |
defaultValue | default-value | string | Not specified | Initial selected value for uncontrolled usage. |
disabled | disabled | boolean | false | Mirror disabled state to the native fieldset. |
orientation | orientation | 'horizontal' | 'vertical' | 'horizontal' | Keyboard orientation. |
Events
| Event | Detail type | Description |
|---|---|---|
rc-segmented-button-change | No detail type documented | Fired after user interaction changes the selected value. |
Slots
| Name | Description |
|---|---|
(default) | A direct `<fieldset>` containing native radio inputs and labels. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-segmented-button-appearance | Not specified | Set to `segmented` to turn on the component's segmented recipe: a flat fieldset, a visually hidden legend, and hidden but focusable radios. Unset, the fieldset, legend, and radios keep their browser appearance. |
--rc-segmented-button-cursor | pointer | Segment cursor once the segmented recipe is on. |
--rc-segmented-button-disabled-cursor | not-allowed | Segment cursor when its radio is disabled, or when the host is `disabled`, once the segmented recipe is on. |
--rc-segmented-button-vertical-divider | Not specified | Border on the inline-start edge of adjacent segments in vertical orientation (defaults to the segment border). |
--rc-segmented-button-selected-icon-display | inline-grid | Display of the selected-icon slot. Set to `none` for a theme that shows selection without a tick. |
--rc-segmented-button-segment-gap | 0.5em | Gap between segment icon and label content. |
--rc-segmented-button-selected-icon-size | 1.25em | Reserved inline-size of the selected-icon slot (and its opposite-side mirror spacer) — constant regardless of checked state, so segment width doesn't change on selection. |
--rc-segmented-button-segment-min-block-size | Not specified | Minimum segment block size (defers to native label layout when unset). |
--rc-segmented-button-segment-padding-block | revert | Segment block-axis padding (defers to native label padding when unset). |
--rc-segmented-button-segment-padding-inline | revert | Segment inline-axis padding (defers to native label padding when unset). |
--rc-segmented-button-border | revert | Segment border (defers to native label border when unset). |
--rc-segmented-button-color | revert | Segment text color (defers to native label color when unset). |
--rc-segmented-button-bg | revert | Segment background (defers to native label background when unset). |
--rc-segmented-button-radius | revert | Rounded corner radius on the first and last segments (defers to native label styling when unset). |
--rc-segmented-button-divider | revert | Border between adjacent segments (defers to native label styling when unset). |
--rc-segmented-button-selected-color | revert | Segment text color when its radio is checked (defers to native label color when unset). |
--rc-segmented-button-selected-bg | revert | Segment background when its radio is checked (defers to native label background when unset). |
--rc-segmented-button-focus-ring | revert | Segment outline when its radio is focus-visible (defers to native focus styling when unset). |
--rc-segmented-button-focus-ring-offset | revert | Segment outline offset when its radio is focus-visible (defers to native focus styling when unset). |
--rc-segmented-button-disabled-opacity | revert | Segment opacity when its radio is disabled, or when the host is `disabled` (defers to native disabled styling when unset). Under `forced-colors: active` the selected segment is restated in system colors (`Highlight` / `HighlightText`), so a selected state stays visible even when a theme paints selection with a background the forced palette replaces, and even when the optional selected-icon slot is not used. |