> ## Oymyakon DS index
> Fetch the full index at: https://super-dollop-pzmo65r.pages.github.io/llms.txt
> HTML preview: https://super-dollop-pzmo65r.pages.github.io/segmented-control.html
> Source: specs/components/segmented-control/segmented-control.md, specs/components/segmented-control/segmented-control-a11y.md

---

# Segmented Control · Oymyakon DS 3

> A horizontal group of mutually exclusive options — one segment is always selected.

**Version:** 3.1.0 · **Status:** Draft

---

## 1. Overview

Segmented Control presents a compact set of choices in a single row. Exactly one segment is active at all times; selecting a new segment deactivates the previous one. Typically used for switching between views, filters, or modes.

The component fills the width of its container (fill). All segments share equal width (fill each). Height is fixed.

---

## 2. Slot structure

```
SegmentedControl
├── track                  container — background, border-radius, padding
│     ├── segment-1        Segment (active by default)
│     ├── segment-2        Segment
│     └── segment-N        Segment (2–5 segments supported)
```

### Segment

```
Segment
├── start-slot             IconContainer · double-color/-dc (optional, hidden by default)
├── label                  text
├── indicator              Indicator · L size (optional, hidden by default)
└── end-slot               IconContainer · double-color/-dc (optional, hidden by default)
```

| Slot | Type | Required | Description |
|---|---|---|---|
| **start-slot** | IconContainer (`double-color`, `-dc` suffix) | Optional | Left icon. Hidden by default |
| **label** | Text | Required | Segment label. Single line, max 1 line, truncates with ellipsis |
| **indicator** | Indicator (L) | Optional | Status dot. Placed after label. Gap to label: s8. Hidden by default |
| **end-slot** | IconContainer (`double-color`, `-dc` suffix) | Optional | Right icon. Hidden by default |

---

## 3. Anatomy (diagram)

```
┌────────────────────────────────────────────────────────────┐  ← track
│  margin: s0 (default)   padding: s4   border-radius: s20   │
│  ┌──────────────────────────┐  ┌──────────────────────┐    │
│  │  [icon]  Label  [•]      │  │  [icon]  Label       │ …  │
│  └──────────────────────────┘  └──────────────────────┘    │
│       segment (active)              segment (default)       │
└────────────────────────────────────────────────────────────┘

Segment detail:
┌──────────────────────────────────────┐
│  s12  [24×24 icon]  s4  Label  s8 [•]  s12  │
│           ↕ s10 padding top/bot             │
└──────────────────────────────────────┘
  border-radius: s16   height: s48
```

---

## 4. Layout & Spacing

### Track

```
height:           var(--sp-s56)
padding:          var(--sp-s4)
border-radius:    var(--sp-s20)
margin:           var(--sp-s0)   (default; any DS sp-token allowed)
background:       var(--background-secondary)
width:            fill
layout:           horizontal autolayout, gap: var(--sp-s0)
```

### Segment

```
height:           var(--sp-s48)
width:            fill (all segments equal)
padding-left:     var(--sp-s12)
padding-right:    var(--sp-s12)
padding-top:      var(--sp-s10)
padding-bottom:   var(--sp-s10)
border-radius:    var(--sp-s16)
layout:           horizontal autolayout, align: center
gap (icon → label):     var(--sp-s4)
gap (label → indicator): var(--sp-s8)
```

---

## 5. Colors

### Track

| Property | Token |
|---|---|
| background | `var(--surface-on-white)` |

### Segment — Active

| Property | Token |
|---|---|
| background | `var(--background-inverse-primary)` |
| text color | `var(--text-and-icon-brand)` |
| icon style | `double-color` (`-dc` suffix) |
| icon vector layer | `doubleColor/outlineInverse` |
| icon bg layer | `doubleColor/bgInverse` |

### Segment — Default (rest)

| Property | Token |
|---|---|
| background | none (transparent) |
| text color | `var(--text-and-icon-primary)` |
| icon style | `double-color` (`-dc` suffix) |
| icon vector layer | `doubleColor/outline` |
| icon bg layer | `doubleColor/bg` |

---

## 6. Typography

### Label

| Property | Token |
|---|---|
| font-family | `var(--text-heading-heading4-family)` |
| font-size | `var(--text-heading-heading4-size)` |
| font-weight | `var(--text-heading-heading4-weight)` |
| line-height | `var(--text-heading-heading4-line-height)` |
| color (active) | `doubleColor/outlineInverse` |
| color (default) | `doubleColor/outline` |
| color (disabled) | `var(--text-and-icon-disabled)` |
| overflow | single line, truncates with ellipsis |

---

## 7. IconContainer

Both `start-slot` and `end-slot` use IconContainer with `double-color` style icons (`-dc` suffix). Hidden by default. When visible:

| Property | Value |
|---|---|
| size | 24 (default) |
| style | `double-color` |
| color | not applicable — built-in colors |
| active state | vector: `doubleColor/outlineInverse` · bg: `doubleColor/bgInverse` |
| default state | vector: `doubleColor/outline` · bg: `doubleColor/bg` |
| rtl | `false` — icons do not flip |

Full spec → [`specs/primitives/icon-container.md`](https://github.com/inDriver/oymyakon-ds/blob/main/specs/primitives/icon-container.md)

---

## 8. Indicator

Indicator component (L size) placed after label. Hidden by default. Gap to label: `var(--sp-s8)`.

Inherits all color styles from the parent segment state (active / default).

Full spec → [`specs/components/indicator/indicator.md`](https://super-dollop-pzmo65r.pages.github.io/indicator.md)

---

## 9. Segment count

| Count | Notes |
|---|---|
| 2 | Minimum |
| 3 | Default / recommended |
| 4 | Supported |
| 5 | Maximum — use only with very short labels or icon-only |

---

## 10. Interaction

- Tap on inactive segment → becomes active; previous active becomes default.
- Tap on active segment → no-op.

---

## 11. Motion

### Thumb (sliding background)

The active segment indicator is an absolutely-positioned element that slides under segments using `transform: translateX()`. Only compositor-friendly properties are animated.

| Property | Token | CSS value |
|---|---|---|
| `transform` (position) | `Transforming/State/Slow` | `300ms cubic-bezier(0.4, 0, 0.2, 1)` |
| `width` (segment resize) | `Transforming/State/Slow` | `300ms cubic-bezier(0.4, 0, 0.2, 1)` |

Curve rationale: `slow-ease-out` — the thumb **moves within** the screen between two points, matching rule §2.5 "Object moves within the screen".

### Text and icon color

| Property | Token | CSS value |
|---|---|---|
| `color` | `Patterns/Color` | `200ms cubic-bezier(0.25, 0.25, 0.75, 0.75)` |
| `fill` (dc-icon layers) | `Patterns/Color` | `200ms cubic-bezier(0.25, 0.25, 0.75, 0.75)` |

Color changes use `linear` — no geometry involved, matching rule §2.4.

### Reduced motion

When `prefers-reduced-motion: reduce` is active — all transitions are set to `0ms`. The thumb jumps instantly to the new position; colors switch without transition.

---

## 12. Accessibility

| Attribute | Element | Value |
|---|---|---|
| `role` | track (`.segmented-control`) | `group` |
| `aria-label` | track | Descriptive label, e.g. `"View mode"` |
| `role` | each segment (`<button>`) | implicit `button` — no override needed |
| `aria-pressed` | active segment | `"true"` |
| `aria-pressed` | inactive segment | `"false"` |
| `tabindex` | each segment | `0` — all segments are focusable |

### Keyboard navigation

| Key | Behavior |
|---|---|
| `Tab` / `Shift+Tab` | Moves focus between segments |
| `Enter` / `Space` | Activates focused segment |
| `←` / `→` | Moves focus to previous / next segment (wraps around) |

---

## 13. Width

- `width: fill` — the control fills its container width.
- `min-width` is not set — the container is responsible for providing adequate space.
- When space is constrained, segment labels truncate with ellipsis (single line).
- Segments never scroll horizontally — they always share available width equally.
- No maximum width constraint.

---

## 14. Gap rules

- `gap (label → indicator): var(--sp-s8)` — present only when the Indicator is visible.
- When the Indicator is hidden, the gap collapses (auto-layout behavior — no reserved space).

---

## 15. Indicator

> **TODO:** Add Indicator usage examples and visual spec once `specs/components/indicator/indicator.md` is complete. Reference: Indicator L size, inherits color from parent segment state.

---

## 16. RTL

Default: RTL = Off.

| Element | RTL behavior |
|---|---|
| Track child order | Reverses on `dir="rtl"` |
| Segment child order | Reverses (`start-slot` moves to right) |
| Icons | `rtl: false` — do not flip |

---

## Changelog

| Version | Date | Changes |
|---|---|---|
| 3.1.0 | 2026-05-13 | Added §11 Motion tokens, §12 Accessibility, §13 Width rules, §14 Gap collapse, §15 Indicator TODO, §16 RTL. Preview page built with sliding thumb animation, dc-icon support, keyboard nav. |
| 3.0.0 | 2026-05-13 | Initial spec: anatomy, slot table, layout & spacing, colors, icon container, segment count, typography. |

---

# Segmented Control · Accessibility Spec · Oymyakon DS 3

**Version:** 1.0.0 · **Status:** Draft · **Linked component:** [`segmented-control.md`](https://super-dollop-pzmo65r.pages.github.io/segmented-control.md)

---

## 1. Roles and Semantics

```html
<div class="segmented-control"
  role="group"
  aria-label="View mode">

  <button class="sc-segment sc-segment--active"
    aria-pressed="true">Ride</button>

  <button class="sc-segment"
    aria-pressed="false">Delivery</button>

  <button class="sc-segment"
    aria-pressed="false">Courier</button>

</div>
```

| Element | Role | Key attribute |
|---|---|---|
| Track (`.segmented-control`) | `group` | `aria-label` — descriptive name for the group (e.g. "View mode") |
| Active segment (`<button>`) | `button` (implicit) | `aria-pressed="true"` |
| Inactive segment (`<button>`) | `button` (implicit) | `aria-pressed="false"` |

All segments are `<button>` elements — no `role` override needed. The `group` role on the track lets screen readers announce the widget as a named container.

---

## 2. Keyboard Navigation

| Key | Behavior |
|---|---|
| `Tab` | Moves focus into the Segmented Control (first or last focused segment) |
| `Shift+Tab` | Moves focus out of the control |
| `Tab` (within) | Moves focus to the next segment |
| `←` Arrow | Moves focus to the previous segment (wraps around) |
| `→` Arrow | Moves focus to the next segment (wraps around) |
| `Space` / `Enter` | Activates the focused segment; updates `aria-pressed` |

All segments are in the tab order (`tabindex="0"`). Focus does not automatically follow the active state — the user must press `Space` or `Enter` to activate.

---

## 3. Focus Indicator

Do not suppress `outline` on `.sc-segment`. The browser's default focus outline is sufficient. Minimum tap target: `var(--sp-s48)` height (enforced by segment height). Horizontal minimum: each segment fills equal share of the track, which is at least `var(--sp-s48)` wide in normal usage.

---

## 4. Contrast Requirements

| Element | Token | Requirement |
|---|---|---|
| Active label | `--text-and-icon-brand` on `--background-inverse-primary` | ≥ 4.5:1 (text) |
| Default label | `--text-and-icon-primary` on `--surface-on-white` | ≥ 4.5:1 (text) |
| Track background | `--surface-on-white` on page background | Decorative — no requirement |
| Active thumb | `--background-inverse-primary` on `--surface-on-white` | ≥ 3:1 (UI component boundary) |

---

## 5. Platform Screen Reader Behavior

### Android · TalkBack

- Track announced as: "View mode, group" (or whatever `aria-label` says)
- Active segment: "{label}, button, pressed" + hint "Double-tap to activate"
- Inactive segment: "{label}, button, not pressed" + hint "Double-tap to activate"
- Arrow key navigation: moves focus + speaks label

### iOS · VoiceOver

- Track announced as: "View mode, group"
- Active segment: "{label}, selected, button" (`.selected` trait)
- Inactive segment: "{label}, button"
- Arrow keys: move focus between segments

---

## 6. Reduced Motion

```css
@media (prefers-reduced-motion: reduce) {
  .sc-thumb   { transition: none; }
  .sc-segment { transition: none; }
  .sc-segment svg .dc-bg,
  .sc-segment svg .dc-vector { transition: none; }
}
```

When reduced motion is on: thumb jumps instantly to the new position; label and icon colors switch without transition.

---

## Changelog

| Version | Date | Change |
|---|---|---|
| 1.0.0 | 2026-05-19 | Initial a11y spec — roles, keyboard, contrast, TalkBack/VoiceOver, reduced motion |
