Segmented Control

Used to pick one choice from a linear set of options

Usage

import { SegmentGroup } from "chakra-ui-solid";
<SegmentGroup.Root>
  <SegmentGroup.Indicator />
  <SegmentGroup.Item>
    <SegmentGroup.ItemText />
    <SegmentGroup.ItemHiddenInput />
  </SegmentGroup.Item>
</SegmentGroup.Root>

A segmented control is a radio group wearing a second set of styles, so one machine drives every SegmentGroup.Item inside a SegmentGroup.Root: the group owns the picked value and a segment owns only its value.

SegmentGroup.Item renders the <label> and SegmentGroup.ItemHiddenInput renders the real <input type="radio"> inside it, so a click anywhere on a segment picks it. The input is not optional — without it there is nothing focusable, nothing to submit, and nothing for the segment to point at.

SegmentGroup.Indicator is the sliding highlight, and there is one for the whole group. The machine measures the picked segment and writes its position and size onto that element, so put it inside the root and let it find its own place.

Shortcuts

The SegmentGroup component also provides a set of shortcuts for common use cases.

SegmentGroup.Items

The SegmentGroup.Items shortcut renders a list of items based on the items prop.

This works:

<For each={items}>
  {(item) => (
    <SegmentGroup.Item value={item.value}>
      <SegmentGroup.ItemText>{item.label}</SegmentGroup.ItemText>
      <SegmentGroup.ItemHiddenInput />
    </SegmentGroup.Item>
  )}
</For>

This might be more concise, if you don’t need to customize the items:

<SegmentGroup.Items items={items} />

Examples

Sizes

Use the size prop to change the size of the segmented control.

size = xs

size = sm

size = md

size = lg

Controlled

Use the value and onValueChange props to control the selected item.

Hook Form

Here’s an example of how to use the segmented control inside a form.

Vertical

By default, the segmented control is horizontal. Set the orientation prop to vertical to change the orientation of the segmented control.

Disabled

Use the disabled prop to disable the segmented control.

Disabled Item

Use the disabled prop on the item to disable it.

Custom Indicator

Customize the indicator appearance using CSS variables like --segment-indicator-bg and --segment-indicator-shadow.

Color Palette

By default, the segment control doesn’t support changing the design via the colorPalette prop. This example shows how to customize the segmented control to make the colorPalette prop work.

Icon

Render the label as markup to render an icon.

Card

Here’s an example of how to use the segmented control within a Card.

Find your dream home

Props

Root

SegmentGroupRootProps
PropDefaultType
defaultValue—
string | null

The radio checked when a fresh, uncontrolled group is rendered.

disabled—
boolean

Whether every radio in the group is disabled. Inherited from a surrounding Fieldset.

form—
string

The id of a form elsewhere on the page that this group submits with.

id—
string

Seeds every id the machine hands out — the root is `radio-group:{id}`, one item's hidden input `radio-group:{id}:radio:input:{value}`. Defaults to a generated id, and **does not become the root element's own `id`**: pass `ids` to control the attributes themselves. It is also the fallback `name` on every hidden input, so a group with no `name` still submits under something stable.

ids—
RadioGroupElementIds

Override individual element ids. The four item-level entries are **functions of the item's value**, because one machine addresses N of each.

invalid—
boolean

Whether every radio shows its error treatment. Inherited from a surrounding Fieldset.

name—
string

The `name` every hidden input submits under. Defaults to {@link CreateRadioGroupProps.id}.

onValueChange—
(details: RadioGroupValueChangeDetails) => void

Called whenever the checked radio changes, from either side.

orientation'horizontal'
'horizontal' | 'vertical'

Which way the segments run — the machine's keyboard model, the `data-orientation` on every part, and what the recipe's `_horizontal` / `_vertical` blocks select on. **This Root is the one place in the radio-group family that defaults it.** The machine's own default is `vertical` and a `RadioCard.Root` never lets it through at all; Chakra passes this Root `defaultProps: { orientation: "horizontal" }`, because a segmented control is a row.

readOnly—
boolean

Whether the group refuses to change while staying focusable.

required—
boolean

Whether the form requires one of these radios to be picked.

size'md'
ConditionalValue<'xs' | 'sm' | 'md' | 'lg' | PresetVariant<'segmentGroup', 'size'>>

Each segment's height, horizontal padding, inner gap and text style.

value—
string | null

The controlled value — the `value` of the checked radio, or `null` for none. `null` means *controlled, and empty*; use `undefined` for uncontrolled.

Plus Omit<HTMLChakraProps<"div">, "id"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

RootProvider

SegmentGroupRootProviderProps
PropDefaultType
size'md'
ConditionalValue<'xs' | 'sm' | 'md' | 'lg' | PresetVariant<'segmentGroup', 'size'>>

Each segment's height, horizontal padding, inner gap and text style.

value*—
CreateSegmentGroupReturn

A machine built by {@link createSegmentGroup}, so the consumer owns it rather than the Root.

Plus HTMLChakraProps<"div"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Item

SegmentGroupItemProps

Adds no prop of its own. It takes everything in zagRadioGroup.ItemProps, HTMLChakraProps<"label"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Items

SegmentGroupItemsProps
PropDefaultType
items*—
Array<string | SegmentGroupItemDescriptor>

A bare string is both the value and the label; the long form separates them.

Plus everything in Omit<SegmentGroupItemProps, "value">, and the three every component takes: as, render and unstyled.