Segmented Control
DIP switch bank radio group — mutually exclusive button row
Size
Material
State
<div class="segmented">
<button class="segmented-item active">PHOTO</button>
<button class="segmented-item">VIDEO</button>
<button class="segmented-item">SLOW</button>
</div> .segmented {
display: inline-flex; background: var(--bg-inset);
border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
padding: 3px; box-shadow: var(--shadow-inset);
}
.segmented-item {
padding: 6px 14px; border: none; background: transparent;
font-family: var(--font-ui); font-size: 10px; font-weight: 500;
letter-spacing: 1px; color: var(--text-muted); cursor: pointer;
border-radius: calc(var(--radius-md) - 2px);
transition: all 0.15s var(--snap-fast);
}
.segmented-item:hover { color: var(--text-primary); }
.segmented-item.active {
background: var(--bg-surface); color: var(--amber);
box-shadow: 0 1px 3px rgba(0,0,0,0.2), inset 0 1px 0 var(--glossy-hi);
} API
| Class | Type | Description |
|---|---|---|
.segmented | Base | Primary component class |
.md | Size | Medium (default) variant |
.glossy | Material | Glossy surface variant |
.active | State | Active state |
Design Notes
Physical Analog
Reference devices: Camera mode selector (Photo/Video/Slow), audio input selector (Mic/Line/Phono), Sony MiniDisc player play-mode switch. Mechanism: DIP switch bank or slide-selector switch. Row of mechanically interlocked buttons where pressing one releases the previously pressed button (mutually exclusive). Each button pushes a metal leaf contact onto a bus bar. Interlock mechanism ensures only one circuit is closed at a time.
Geometry
| Property | Value |
|---|---|
| Track | Recessed (bg-inset with inset shadow) |
| Segment padding | 6px 14px |
| Border-radius | var(--radius-md) outer, -2px inner |
| Active segment | Raised with shadow and glossy highlight |
CSS Recipe
Container (Track)
.segmented {
display: inline-flex; background: var(--bg-inset);
border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
padding: 3px; box-shadow: var(--shadow-inset);
}
Segment Item
.segmented-item {
padding: 6px 14px; border: none; background: transparent;
font-family: var(--font-ui); font-size: 10px; font-weight: 500;
letter-spacing: 1px; color: var(--text-muted); cursor: pointer;
border-radius: calc(var(--radius-md) - 2px);
transition: all 0.15s var(--snap-fast);
}
Hover State
.segmented-item:hover { color: var(--text-primary); }
Active (Selected) State
.segmented-item.active {
background: var(--bg-surface); color: var(--amber);
box-shadow: 0 1px 3px rgba(0,0,0,0.2), inset 0 1px 0 var(--glossy-hi);
}
HTML Structure
<div class="segmented">
<button class="segmented-item active">PHOTO</button>
<button class="segmented-item">VIDEO</button>
<button class="segmented-item">SLOW</button>
</div>
Size Variants
No explicit size variants defined.
Material Variants
- Track: Recessed panel (phosphor screen cavity)
- Active segment: Raised glossy surface with specular highlight
Theme Behavior
--bg-insetprovides the recessed track color per theme--shadow-insetadapts shadow intensity per theme- Active segment surface and shadow adapt via tokens
Constraints
- Only ONE item can be
.activeat a time (radio behavior, NOT multi-select). - Active item MUST look physically raised relative to the track -- use shadow and highlight to create depth differential.
- Track padding (3px) creates the visible gap between segment buttons and track walls.
- Inner border-radius MUST be
calc(var(--radius-md) - 2px)to nest correctly inside outer radius.
Accessibility
- Uses native
<button>elements - Keyboard: Arrow keys to navigate between segments, Enter to select
- ARIA: Container should use
role="radiogroup", items should userole="radio"witharia-checked - Requires JS to toggle
.activeclass between items (mutual exclusion)
♿
Accessibility
- Element
- Use native <button> element
- Keyboard
- Enter or Space to activate
- Focus
-
Visible focus indicator required. Use native browser focus ring or custom
:focus-visiblestyles.