Segmented control
SvSegmented: mutually-exclusive options in a shared track (a view switcher, a range picker). Single-select, keyboard-accessible (arrow keys + Space/Enter via the radio-group core), with sizes, full-width, icons and disabled states. Themed from the --sg-* tokens.
A live, editable Svelte 5 component example from the SvGrid gallery (Buttons & Toggles). Read the SvGrid UI component docs for the full API.
About this example
SvSegmented, a segmented control for Svelte 5: mutually exclusive options in a shared track, used as a view switcher and a range picker. It is single-select and keyboard accessible with arrow keys and Space or Enter through the radio-group core, supports icons per option, disabled options and a full-width block layout, binds its value and is themed from the --sg-* tokens as the modern alternative to a small radio group.
SvSegmented - a segmented control: mutually-exclusive options in a shared track. Single-select, keyboard-accessible (arrow keys + Space/Enter), and themed from the --sg-* tokens. The modern alternative to a small radio group.
Imports, features and API used
Imports: @svgrid/grid
Frequently asked questions
How do I bind the selection?
Use bind:value with the options array of { value, label }. The selected segment slides into place and the bound value updates.
When should I use a segmented control over tabs?
For a small set of mutually exclusive choices that change a view or a parameter, such as Board and Table or Day and Week. Tabs suit larger content panels.
Can segments show icons?
Yes. Each option can carry an icon snippet with or without a label, and block mode stretches the segments across the container.
Related documentation
Related articles
- SvGrid UI Components Tips and Tricks: Svelte 5 Buttons, Inputs, Tree, Forms - Practical tips for the SvGrid UI component kit - SvButton states, a Cmd+K command palette, a virtualized searchable tree, schema-driven forms, a parsing date/time field, and the shared field contract - each with a code snippet.
- Controlled vs Uncontrolled Grid State - Who owns sort, filter, and page state - you or the grid? The answer shapes your whole integration. Here is how to think about it and when each mode pays off.
- $bindable Props for Grid Controls in Svelte 5 - Two-way binding for grid chrome - search boxes, page-size selectors, density toggles - using $bindable to keep parent state and child input in sync without the usual wiring boilerplate.
Source code (408-segmented.svelte)
<script lang="ts">
/**
* SvSegmented - a segmented control: mutually-exclusive options in a shared
* track. Single-select, keyboard-accessible (arrow keys + Space/Enter), and
* themed from the --sg-* tokens. The modern alternative to a small radio group.
*/
import { SvSegmented } from '@svgrid/grid'
let view = $state('board')
let range = $state('7d')
let density = $state('comfortable')
let align = $state('left')
</script>
<div class="wrap">
<section>
<h3>View switcher</h3>
<SvSegmented
label="View"
bind:value={view}
options={[{ value: 'board', label: 'Board' }, { value: 'table', label: 'Table' }, { value: 'calendar', label: 'Calendar' }]}
/>
<p class="muted">Selected: <strong>{view}</strong></p>
</section>
<section>
<h3>Sizes</h3>
<div class="col">
<SvSegmented size="sm" bind:value={range} options={[{ value: '24h', label: '24h' }, { value: '7d', label: '7d' }, { value: '30d', label: '30d' }]} />
<SvSegmented size="md" bind:value={range} options={[{ value: '24h', label: '24h' }, { value: '7d', label: '7d' }, { value: '30d', label: '30d' }]} />
<SvSegmented size="lg" bind:value={range} options={[{ value: '24h', label: '24h' }, { value: '7d', label: '7d' }, { value: '30d', label: '30d' }]} />
</div>
</section>
<section>
<h3>Full width + icons</h3>
<SvSegmented block bind:value={align} options={[
{ value: 'left', label: 'Left', icon: iconLeft },
{ value: 'center', label: 'Center', icon: iconCenter },
{ value: 'right', label: 'Right', icon: iconRight },
]} />
</section>
<section>
<h3>Disabled</h3>
<SvSegmented disabled bind:value={density} options={[{ value: 'comfortable', label: 'Comfortable' }, { value: 'compact', label: 'Compact' }]} />
</section>
</div>
{#snippet iconLeft()}<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M4 12h10M4 18h13" /></svg>{/snippet}
{#snippet iconCenter()}<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M7 12h10M6 18h12" /></svg>{/snippet}
{#snippet iconRight()}<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M10 12h10M7 18h13" /></svg>{/snippet}
<style>
.wrap { padding: 22px; display: flex; flex-direction: column; gap: 24px; max-width: 460px; }
section h3 { margin: 0 0 10px; font-size: 14px; font-weight: 700; }
.col { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.muted { margin: 8px 0 0; color: var(--sg-muted, #64748b); font-size: 13px; }
</style>More Buttons & Toggles examples
- Buttons & toggles - The UI kit press/toggle primitives: SvButton (variants/sizes/loading), SvRepeatButton (hold-to-repeat), SvToggleButton, SvSwitchButton, SvCheckBox (+ indeterminate), SvRadioGroup (arrow-key nav) and SvRating (half stars). Theme-driven, standalone or as grid cell controls.
- Button group - SvButtonGroup: a segmented button bar - single-select (radio semantics, a view switcher), multi-select (a toggle set / formatting toolbar) or plain actions. Roving tabindex + arrow keys, and the shared editor contract (label, validation, dir/RTL).
- Button - SvButton in production: a toolbar (variants primary/secondary/outline/ghost/danger), sizes, icon slots, a loading state and a full-width CTA. Copy-paste-ready blocks.
- Repeat button - SvRepeatButton: hold-to-repeat with acceleration - a quantity stepper and a volume control block.
- Toggle button - SvToggleButton: a pressed on/off button (aria-pressed) - a text-formatting toolbar and pin / live state toggles.