<!-- Protocore Design System — PeriodSelector -->
# PeriodSelector

- **Category:** Charts (`charts`)
- **Slug:** `charts/period-selector`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { PeriodSelector } from "@protocore/pds/charts";`
- **Docs:** https://pds.protocore.io/components/charts/period-selector

> A 1D/1W/1M/1Y time-range toggle for chart headers, built on SegmentedControl with radiogroup semantics.

## Import path

Unlike the recharts wrappers, `PeriodSelector` ships from the **main `@protocore/pds`** entry — it carries no recharts dependency, it is a thin `SegmentedControl` for chart headers.

```tsx
import { PeriodSelector, ChartContainer } from "@protocore/pds";
```

## When to use it

Use **PeriodSelector** for the *time-range switch* that sits in a chart or dashboard header. It is a preset over [SegmentedControl](/inputs/segmented-control) — for any other small single-select toggle (a view mode, a unit) reach for `SegmentedControl` directly.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `periods` | `PeriodOption[]` | no | `1D / 1W / 1M / 1Y` | The periods, left to right. `PeriodOption` = `{ value: string; label: ReactNode; disabled?: boolean }`. |
| `value` | `string` | no | — | Controlled selected value. |
| `defaultValue` | `string` | no | `first period's value` | Uncontrolled initial selected value. |
| `onValueChange` | `(value: string) => void` | no | — | Fired with the newly-selected period value. |
| `disabled` | `boolean` | no | `false` | Disable the whole control. |
| `aria-label` | `string` | no | `"Time range"` | Accessible name for the range group. |

## Examples

### Basics

Rendered on its own it shows the house `1D / 1W / 1M / 1Y` ranges with the first selected. It is a single-select toggle: exactly one range stays active, and `onValueChange` fires with the chosen value.

```tsx
import { useState } from "react";
import { PeriodSelector } from "@protocore/pds";

export default function Demo() {
  const [range, setRange] = useState("1W");
  return <PeriodSelector value={range} onValueChange={setRange} aria-label="Time range" />;
}
```

### In a chart header

Drop it into a [ChartContainer](/charts/chart-container) `actions` slot to switch the range a chart plots. Pass a custom `periods` list when your ranges differ from the defaults.

```tsx
import { useMemo, useState } from "react";
import { ChartContainer, PeriodSelector } from "@protocore/pds";
import { AreaChart } from "@protocore/pds/charts";

const SERIES: Record<string, Array<{ t: string; v: number }>> = {
  "1D": [
    { t: "00", v: 32 },
    { t: "06", v: 41 },
    { t: "12", v: 58 },
    { t: "18", v: 47 },
  ],
  "1W": [
    { t: "Mon", v: 240 },
    { t: "Wed", v: 310 },
    { t: "Fri", v: 280 },
    { t: "Sun", v: 360 },
  ],
  "1M": [
    { t: "W1", v: 1200 },
    { t: "W2", v: 1580 },
    { t: "W3", v: 1410 },
    { t: "W4", v: 1720 },
  ],
  "1Y": [
    { t: "Q1", v: 14000 },
    { t: "Q2", v: 16800 },
    { t: "Q3", v: 15200 },
    { t: "Q4", v: 19100 },
  ],
};

export default function Demo() {
  const [range, setRange] = useState("1W");
  const data = useMemo(() => SERIES[range] ?? [], [range]);
  return (
    <ChartContainer
      label="Requests"
      actions={<PeriodSelector value={range} onValueChange={setRange} aria-label="Time range" />}
      height={220}
    >
      <AreaChart data={data} xKey="t" series={[{ key: "v", label: "Requests" }]} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Place it in a ChartContainer `actions` slot beside the chart it controls.
- Keep range labels terse (`1D`, `1W`) — it is a toggle, not a menu.
- Wire `onValueChange` to refetch or reslice the plotted data.
- Override `periods` when your ranges differ from 1D/1W/1M/1Y.

**Don't**

- Don't use it for multi-select — exactly one range stays active.
- Don't pack in many long labels; use a Select for a large range list.
- Don't forget an `aria-label` if the context isn't obvious.
- Don't reach for it for non-range toggles — use SegmentedControl.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Arrow keys` | Move between ranges (Radix ToggleGroup roving focus). |
| `Tab` | Move focus into and out of the range group. |
| `Enter / Space` | Select the focused range. |

**Notes**

- Built on Radix ToggleGroup with radiogroup semantics; exposes `role=radiogroup` with `role=radio` segments.
- Always keeps exactly one range selected — deselection is not possible.
- Give an `aria-label` (defaults to `Time range`) so the group is named for assistive tech.

## Related

`segmented-control`, `chart-container`, `line-chart`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
