# Multi-step stories (/docs/guides/stories)

> Use sequence() to join several authored states into one seekable timeline.

When a chart moves through more than two states, build them all up front and
pass them to `sequence()`. You get one controller for the whole timeline, with
no empty frame between legs.

<LiveExample id="bar-story" />

## Build the states [#build-the-states]

```ts
import { bar } from 'visdelta/bar';
import { sequence } from 'visdelta/transition';

const revenue = bar(products).x('product').y('revenue');
const profit = revenue.y('profit');
const ranked = profit.sort('profit', 'descending');
const emphasised = ranked.highlight({ product: 'Software' });

const story = await sequence([revenue, profit, ranked, emphasised], {
  target: '#chart',
});
```

All states must use the same chart type. To return to the start, repeat the
first state at the end: `[revenue, profit, ranked, revenue]`.

## Seek in leg units [#seek-in-leg-units]

A sequence's `value` runs from `0` to `states.length - 1`. Integers are the
authored states; fractions are positions within a leg.

```ts
story.progress(0);      // revenue
story.progress(1.5);    // halfway from profit to ranked
story.progress(3);      // emphasised
story.play({ to: 2 });  // from the current position to ranked
```

## Scroll-driven steps [#scroll-driven-steps]

Start from the [single-file scroll template](/docs/guides/scroll-template).
It maps measured step positions to sequence leg units, holds each authored
state before advancing, and handles reverse scrolling, replay, resize,
reduced motion and iframe fallback. Keep scroll control outside the library.

The [progress model](/docs/concepts/progress) explains why authored states stay
at integers even when the planner inserts extra route stages.

## Authored states are fixed [#authored-states-are-fixed]

Each state you pass is a boundary the planner keeps. Within each pair, the
chart may still insert generated stages; these occupy the existing leg and do
not shift integer positions. They do add playback time, because `duration`
applies to every serial stage. See [Progress](/docs/concepts/progress#play).
