components / segmentedcontrol

SegmentedControl

Single-selection segmented control for tight mode switching and compact option clusters.

Overview

What it is

This section explains the intent of the component before the implementation details.

  • SegmentedControl offers faster, denser view switching than RadioGroup when options are short and mutually exclusive.
  • It works best when the options behave like modes rather than form answers.

Aliases

segments

Decision guide

How to choose it

Use these notes to decide quickly whether this is the right DK component for the job.

Decision guide

  • Choose SegmentedControl when the interaction should feel deliberate, documented, and reusable across product surfaces.
  • If the scenario is more specialized than the current SegmentedControl contract, prefer a simpler component or build a dedicated workflow on top of the lower-level DK primitives.

Do

  • Keep the SegmentedControl label, value, or status language direct enough to scan quickly.
  • Use the documented size and state recipes instead of inventing one-off variants in product code.

Do not

  • Do not hide the main purpose of SegmentedControl behind decorative copy or overloaded surface treatments.
  • Do not stretch SegmentedControl into a workflow it was not designed to handle just because the visuals are close.

Usage

When to use

Prefer these situations when choosing this component.

  • Use SegmentedControl for compact mode switches such as day/week/month or card/list.
  • Keep labels short so the control stays scan-friendly.

Usage

When not to use

These patterns are better served by a different component or a simpler surface.

  • Do not use SegmentedControl for long or descriptive options; use RadioGroup instead.
  • Do not use it when the options should live in a toolbar or tabset with larger panel changes.

Anti-patterns

  • Using SegmentedControl as a generic layout container instead of a purpose-built interaction or content surface.
  • Forking the documented recipe in product code instead of extending the shared DK contract.

Migration notes

  • Migrate legacy segmentedcontrol usage by mapping existing variants and states onto the documented DK props before porting any custom styling.
  • Treat the docs examples as the reference contract for accessibility and event behavior during adoption.

Anatomy

Structural parts

The anatomy explains which pieces matter to the recipe and accessibility model.

segmented group

root

Holds the compact option cluster.

single segment

item

Each mutually exclusive segment button.

API

Public interface

The docs contract distinguishes props, DOM events, and slots so integration behavior is explicit.

Props

NameTypeDefaultDescription
valuestringControlled selected segment.
itemsArray<{ value: string; label: string; disabled?: boolean }>Segment definitions.
size'sm' | 'md''md'Chooses the size recipe.
onChange(detail: { value: string | undefined }) => voidCallback fired when the selected segment changes.
themeThemeContractOverrides the compiled DK theme used to resolve tokens and recipes for this component.

Events

NamePayloadDescription
change{ value: string | undefined }Fires when the component commits a new value.

Slots

NameDescription
defaultSegmentedControl is data-driven in v1 and does not expose segment slots.

Recipes

Variants, sizes, and states

These notes summarize the intended recipe surface rather than exposing raw implementation detail first.

Variants

  • default: SegmentedControl uses one compact mode-switching recipe.

Sizes

  • sm: Compact segments
  • md: Default segments

States

  • rest: Unselected segment
  • selected: Active segment
  • disabled: Unavailable segment

Accessibility

Accessibility contract

This is the behavior the component promises to assistive tech and keyboard users today.

Semantics

  • Exposes a single-selection grouped control with clearly labeled options.

Keyboard

  • Arrow-key movement should feel predictable across the segment set.

Screen readers

  • The selected state should be obvious without relying on color alone.

Checklist

  • Verify the visible label or title still produces a clear accessible name.
  • Verify focus remains obvious in every supported state and size.
  • Verify disabled, selected, and error states do not rely on color alone.

Implementation

Tokens and slot vars

This section shows the representative compiled slot variables that the runtime consumes for the selected design system.

root

--dk-segmented-gap
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

group

--dk-segmented-group-bg
#e5e8ed
--dk-segmented-group-border
#95989d
--dk-segmented-group-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-segmented-group-gap
clamp(0.563rem, 0.5156rem + 0.208vw, 0.703rem)
--dk-segmented-group-padding
0.1875rem

item

--dk-segmented-item-bg
#e5e8ed
--dk-segmented-item-fg
#16181c
--dk-segmented-item-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-segmented-item-block-size
44px
--dk-segmented-item-inline-padding
clamp(1.778rem, 1.6296rem + 0.658vw, 2.222rem)
--dk-segmented-item-font-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-segmented-item-font-weight
650

label

--dk-segmented-label-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)

Implementation notes

  • SegmentedControl is optimized for short labels and quick mode changes, not descriptive choices.

Implementation checklist

  • Use the public component API first and only drop to lower-level primitives when the component contract genuinely does not fit.
  • Keep theme overrides token-driven so proofs and recipes stay meaningful.
  • Verify the shipped examples and proof fixtures still represent the real product scenario you are implementing.

Examples

Copy-paste examples

Each example is intentionally practical, grouped by starter, common pattern, and edge-case coverage.

Examples
3
Depth
baseline

Starter

1 example

starter

Starter: mode switch

A compact day/week/month switch.

Copy snippet

<SegmentedControl items={[{ value: 'day', label: 'Day' }, { value: 'week', label: 'Week' }, { value: 'month', label: 'Month' }]} value="week" />

Common patterns

1 example

common

Common: dense toolbar mode

Smaller segments work well in inspector-style toolbars.

Copy snippet

<SegmentedControl size="sm" items={viewItems} value="list" />

Edge cases

1 example

edge

Edge: unavailable segment

Disable segments when a mode exists conceptually but is not usable yet.

Copy snippet

<SegmentedControl items={[{ value: 'day', label: 'Day' }, { value: 'quarter', label: 'Quarter', disabled: true }]} value="day" />

Verification

Curated proof fixtures

Proofs stay visible in the docs so the system shows what it can guarantee, not just what it can render.

default (size=sm)

pass

size=sm

  • Contrast: 90.8 Lc
  • Target: 44px

default (size=md)

pass

size=md

  • Contrast: 90.8 Lc
  • Target: 44px

selected (size=sm)

pass

size=sm

  • Contrast: 89.9 Lc
  • Target: 44px

selected (size=md)

pass

size=md

  • Contrast: 89.9 Lc
  • Target: 44px