# Timeline



This example demonstrates how to create a zoomable timeline chart using `Range`, `ClipRect`, and `Marker` components. The lower chart serves as a navigator with draggable handles to control the visible range in the main chart above.

```tsx
import { Svg, Rectangle, ClipRect } from "cx/svg";
import {
  Chart,
  TimeAxis,
  NumericAxis,
  Range,
  Marker,
  Gridlines,
  ColumnGraph,
} from "cx/charts";
import { createModel } from "cx/data";
import { Controller } from "cx/ui";

interface Point {
  date: Date;
  value: number;
}

interface Model {
  data: Point[];
  range: {
    from: number;
    to: number;
  };
}

const m = createModel<Model>();

class PageController extends Controller {
  onInit() {
    this.store.set(m.range, {
      from: new Date(2011, 0, 1).valueOf(),
      to: new Date(2012, 0, 1).valueOf(),
    });

    let v = 2000;
    this.store.set(
      m.data,
      Array.from({ length: 10 * 12 }, (_, i) => ({
        date: new Date(2005, i, 1),
        value: (v = v + Math.random() * 300 - 150),
      })),
    );
  }
}

const DAY = 24 * 60 * 60 * 1000;

export default (
  <div controller={PageController}>
    <Svg style="width: 100%; height: 500px" margin="60 10 60 60">
      <Chart
        anchors="0 1 0.8 0"
        offset="0 0 -50 0"
        axes={{
          x: (
            <TimeAxis min={m.range.from} max={m.range.to} snapToTicks={false} />
          ),
          y: <NumericAxis vertical />,
        }}
      >
        <Rectangle fill="white" />
        <Gridlines />
        <ClipRect>
          <ColumnGraph
            data={m.data}
            colorIndex={4}
            offset={15 * DAY}
            size={30 * DAY}
            xField="date"
            yField="value"
          />
        </ClipRect>
      </Chart>

      <Chart
        anchors="0.8 1 1 0"
        axes={{
          x: <TimeAxis />,
          y: <NumericAxis vertical />,
        }}
      >
        <Rectangle fill="white" />
        <Gridlines />
        <ColumnGraph
          data={m.data}
          size={30 * DAY}
          offset={15 * DAY}
          xField="date"
          yField="value"
        />

        <Range x1={m.range.from} x2={m.range.to} hidden>
          <ClipRect>
            <ColumnGraph
              data={m.data}
              colorIndex={4}
              size={30 * DAY}
              offset={15 * DAY}
              xField="date"
              yField="value"
            />
          </ClipRect>
          <Range
            colorIndex={4}
            x1={m.range.from}
            x2={m.range.to}
            style="cursor: move"
            draggableX
            constrainX
          />
        </Range>

        <Marker
          colorIndex={4}
          x={m.range.from}
          size={10}
          draggableX
          constrain
        />

        <Marker colorIndex={4} x={m.range.to} size={10} draggableX constrain />
      </Chart>
    </Svg>
  </div>
);

```

## How It Works

1. **Two charts in one Svg** - The main chart uses `anchors` to occupy the top 80%, while the navigator chart takes the bottom 20%
2. **Dynamic range** - The main chart's `TimeAxis` binds its `min` and `max` to the range values
3. **Draggable selection** - `Range` with `draggableX` allows moving the entire selection, while `Marker` components with `draggableX` adjust individual boundaries
4. **ClipRect** - Clips the column graph to the visible area in both charts
5. **Visual feedback** - The selected range in the navigator is highlighted with a different color

## Configuration

| Property     | Type      | Description                                              |
| ------------ | --------- | -------------------------------------------------------- |
| `anchors`    | `string`  | Position chart within Svg: `"top right bottom left"`.    |
| `draggableX` | `boolean` | Enable horizontal dragging on Range or Marker.           |
| `constrainX` | `boolean` | Constrain Range dragging to chart bounds.                |
| `constrain`  | `boolean` | Constrain Marker dragging to chart bounds.               |
| `hidden`     | `boolean` | Hide the Range background while keeping children visible.|