Skip to main content

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

Installation​

npm install @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.

KeyAction
Right Arrow, Down ArrowSelects and focuses the next segment, wrapping to the first.
Left Arrow, Up ArrowSelects and focuses the previous segment, wrapping to the last.
Home, EndSelects 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.

Browser support

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​

PropertyMarkupTypeDefaultDescription
valuevaluestringNot specifiedCurrent selected radio value. Host writes are silent.
defaultValuedefault-valuestringNot specifiedInitial selected value for uncontrolled usage.
disableddisabledbooleanfalseMirror disabled state to the native fieldset.
orientationorientation'horizontal' | 'vertical''horizontal'Keyboard orientation.

Events​

EventDetail typeDescription
rc-segmented-button-changeNo detail type documentedFired after user interaction changes the selected value.

Slots​

NameDescription
(default)A direct `<fieldset>` containing native radio inputs and labels.

CSS Custom Properties​

PropertyDefaultDescription
--rc-segmented-button-appearanceNot specifiedSet 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-cursorpointerSegment cursor once the segmented recipe is on.
--rc-segmented-button-disabled-cursornot-allowedSegment cursor when its radio is disabled, or when the host is `disabled`, once the segmented recipe is on.
--rc-segmented-button-vertical-dividerNot specifiedBorder on the inline-start edge of adjacent segments in vertical orientation (defaults to the segment border).
--rc-segmented-button-selected-icon-displayinline-gridDisplay of the selected-icon slot. Set to `none` for a theme that shows selection without a tick.
--rc-segmented-button-segment-gap0.5emGap between segment icon and label content.
--rc-segmented-button-selected-icon-size1.25emReserved 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-sizeNot specifiedMinimum segment block size (defers to native label layout when unset).
--rc-segmented-button-segment-padding-blockrevertSegment block-axis padding (defers to native label padding when unset).
--rc-segmented-button-segment-padding-inlinerevertSegment inline-axis padding (defers to native label padding when unset).
--rc-segmented-button-borderrevertSegment border (defers to native label border when unset).
--rc-segmented-button-colorrevertSegment text color (defers to native label color when unset).
--rc-segmented-button-bgrevertSegment background (defers to native label background when unset).
--rc-segmented-button-radiusrevertRounded corner radius on the first and last segments (defers to native label styling when unset).
--rc-segmented-button-dividerrevertBorder between adjacent segments (defers to native label styling when unset).
--rc-segmented-button-selected-colorrevertSegment text color when its radio is checked (defers to native label color when unset).
--rc-segmented-button-selected-bgrevertSegment background when its radio is checked (defers to native label background when unset).
--rc-segmented-button-focus-ringrevertSegment outline when its radio is focus-visible (defers to native focus styling when unset).
--rc-segmented-button-focus-ring-offsetrevertSegment outline offset when its radio is focus-visible (defers to native focus styling when unset).
--rc-segmented-button-disabled-opacityrevertSegment 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.