---
title: Segmented Control
description: Shared Astro style recipes for related radio choices, navigation links, and pressed buttons.
seo:
    title: Segmented controls for Astro — radio, link, and toggle examples
---

```astro
---
import { RadioGroup } from "@/components/ui/radio-group"
import { Toggle } from "@/components/ui/toggle"
import {
  segmentedControlRootClassName,
  segmentedControlItemVariants,
} from "@gnosticai/ui/lib/segmented-control"
---

<div class="grid gap-6">
  {(["sm", "default", "lg"] as const).map((size) => (
    <RadioGroup
      name={`billing-${size}`}
      defaultValue="monthly"
      aria-label={`Billing period, ${size}`}
      class={`${segmentedControlRootClassName} flex-row`}
    >
      <button
        type="button"
        data-slot="radio-group-item"
        data-value="monthly"
        class={segmentedControlItemVariants({ size, state: "checked" })}
      >
        Monthly
      </button>
      <button
        type="button"
        data-slot="radio-group-item"
        data-value="yearly"
        class={segmentedControlItemVariants({ size, state: "checked" })}
      >
        Yearly
      </button>
    </RadioGroup>
  ))}
  <nav aria-label="Project guides" class={segmentedControlRootClassName}>
    <a
      class={segmentedControlItemVariants({ state: "current" })}
      href="/components/segmented-control"
      aria-current="page"
    >
      Choices
    </a>
    <a
      class={segmentedControlItemVariants({ state: "current" })}
      href="/components/tabs"
    >
      Panels
    </a>
    <a
      class={segmentedControlItemVariants({ state: "current" })}
      href="/components/group"
    >
      Actions
    </a>
  </nav>
  <div
    role="group"
    aria-label="Independent view options"
    class={segmentedControlRootClassName}
  >
    <Toggle
      defaultPressed
      class={segmentedControlItemVariants({ state: "pressed" })}
    >
      Guides
    </Toggle>
    <Toggle class={segmentedControlItemVariants({ state: "pressed" })}>
      Grid
    </Toggle>
  </div>
</div>
```

## Installation

```sh
bunx --bun shadcn@latest add @gnosticai/segmented-control
```

The recipe supplies classes. Add the control used by your composition:

```sh
bunx --bun shadcn@latest add @gnosticai/radio-group @gnosticai/toggle
```

## Usage

```ts
import {
	segmentedControlRootClassName,
	segmentedControlItemVariants,
	segmentedControlItemLayoutClassName,
} from "@/lib/segmented-control"
```

Apply the root class to a group or navigation element. Apply the item recipe to
each child. The radio example uses the existing RadioGroup controller with
button elements marked `data-slot="radio-group-item"` and stable `data-value`
attributes. Its `flex-row` class changes the group's usual column layout.

## API reference

`size` accepts `sm`, `default`, or `lg`. `state` accepts `checked`, `current`, or
`pressed`. These recipes read `data-checked`, `aria-current="page"`, and
`aria-pressed="true"`, respectively. Read the [source](/r/segmented-control.json)
for all exported classes and types.

## Choose the underlying control

Use Radio Group for one form value. Use links for destinations, with
`aria-current="page"` on the current route. Use Toggle for independent options.
Adjacent toggles do not become an exclusive Toggle Group. Use
[Tabs](/components/tabs) when a choice shows a matching content panel; Tabs keeps
its own indicator and panel relationships.

## Keyboard and form behavior

The recipe has no client script. Radio Group keeps its arrow-key selection and
named form value. Links keep browser navigation and open-in-new-tab behavior.
Toggle keeps its pressed state and Space activation. Give each group a name
that explains the shared choice and test disabled items in the final page.

## Theme and layout

The outer muted surface and selected item use shared theme tokens. Keep the
labels short and choose one size for the group. A long row can need a different
layout on a phone; a segmented appearance does not provide overflow controls.
Use [Group](/components/group) for joined action buttons with visible borders.
