← All proposals

Milestone

Net-new, in two parts, in their own family so "timeline" keeps one meaning (the log).

Net-new componentOpen in Storybook

proposals/Milestone/MilestoneList.mdx55 lines · View on GitHub
import { Canvas, Controls, Meta, Title } from '@storybook/addon-docs/blocks';

import * as MilestoneListStories from './MilestoneList.stories';

<Meta of={MilestoneListStories} name='Usage' />

<Title />

## Purpose

A list of milestones on one line: steps people read in order, such as the stages of an application process, each with a heading, a subtitle and a short body.

## TL;DR: Chain of Thought, Timeline or Milestone List?

- **Chain of Thought:** an agent's reasoning under a reply, behind a summary line ("Thought for 17s") that opens on demand. No line, no rail.
- **Timeline:** events that happened or are happening, one line each (status icon, label, time). Always open, and the main content of a screen: a deploy history, an event log, an agent's run. Optional rail between the icons.
- **Milestone List:** steps people read in order, often still ahead of them, with a heading and a paragraph each on a card. One line runs down the whole list: the stages of an application process.

Quick test:

1. Do the steps sit under a reply and need to stay out of the way? **Chain of Thought.**
2. Otherwise, does each entry have a status icon or a time at the end of the row? **Timeline.**
3. Otherwise, does each have a heading and a paragraph? **Milestone List.**

A Chain of Thought is built from a Timeline and uses the same rows, and it can sit inside a Timeline as one entry in a log. Do not mix Timeline Items and Milestones in one list.

## Usage

Use it for a timeline of milestones. For a log of events that happened (deploys, checks, an agent's work), use Timeline instead; the Timeline page compares the two and Chain of Thought.

- Each child becomes a list item; put Milestones in it.
- Milestones sit on the default Panel. `variant='flat'` turns the cards off for text on the line; a Milestone can set `variant` itself to differ from the rest.
- `subtitlePosition='above'` puts each subtitle over the title, as its eyebrow; the dot sits on that line.
- `padding='none'` removes the list’s own space above the first milestone and below the last. Use it when the list sits in a container that already has padding, such as a Panel.
- A Milestone’s `badgeLabel` puts a PDS Badge beside its subtitle, for example “You’re here” (`badgeColor` and `badgeSize` set its type and size). With `subtitlePosition='start'` the Badge stacks under the subtitle, aligned to the same end.
- A Milestone’s `children` is everything under the title: put the description in it, then anything else (a table, a summary, a form). Blocks in it sit a small, fixed distance apart (`spacing-xs`).
- `subtitlePosition='start'` moves each subtitle to the left of the line, beside the dot, and falls back to under the title only at phone widths (under 480px).

## Implementation

The table below lists the props of the Milestone List and of the Milestone, and says which component each belongs to. The first milestone in the examples is the one the controls change. The Milestone page has the same table and the same examples.

## Accessibility

- The list is an `ol` with an `li` per milestone, so assistive technology announces the number of steps and the position in the list.
- The title is a heading; set `headingLevel` to fit the page's outline.
- The line and the dots are decorative and hidden from assistive technology.
- The milestone in focus (`isActive`) has `aria-current='step'`. A Badge in the subtitle says the same in words for people who see the screen.
- Wrap a date in a `time` element for a machine-readable value.

<hr />

<Canvas of={MilestoneListStories.Default} />
<Controls of={MilestoneListStories.Default} />