Skip to content

Timeline

Timeline provides composable primitives for building time-based layouts such as Gantt charts, schedules, and project timelines. It is a compound component with five sub-components: Root, Viewport, Row, Interval, and Link.

Import

tsx
import { Timeline } from "@tailor-platform/app-shell";

Basic Usage

tsx
import { Timeline } from "@tailor-platform/app-shell";

<Timeline.Root start={0} end={100}>
  <Timeline.Viewport
    axis={{
      guides: [{ at: 0 }, { at: 50 }, { at: 100 }],
      levels: [
        {
          kind: "spans",
          items: [
            { start: 0, end: 50, label: "Phase 1" },
            { start: 50, end: 100, label: "Phase 2" },
          ],
        },
      ],
    }}
  >
    <Timeline.Row height={40}>
      <Timeline.Interval start={10} end={35}>
        <div className="h-full rounded-md bg-primary" />
      </Timeline.Interval>
    </Timeline.Row>
  </Timeline.Viewport>
</Timeline.Root>;

Sub-components

Sub-componentDescription
Timeline.RootProvides the shared time range for all nested timeline primitives
Timeline.ViewportRenders the axis, decorations, scrolling area, and link overlay layer
Timeline.RowDefines one horizontal lane with a fixed height and optional background
Timeline.IntervalPositions content across a time range inside a row
Timeline.LinkDraws an orthogonal dependency connector between two named Interval elements

TimeValue

All time position props (start, end, at) accept either a Date object or a millisecond-precision number timestamp.

tsx
// Using Date objects
<Timeline.Root start={new Date("2024-01-01")} end={new Date("2024-12-31")}>

// Using numeric timestamps
<Timeline.Root start={0} end={100}>

Props

Timeline.Root Props

PropTypeDefaultDescription
startDate | numberInclusive start of the overall timeline range
endDate | numberInclusive end of the overall timeline range
childrenReact.ReactNodeTimeline subtree, usually a Timeline.Viewport
classNamestringAdditional CSS classes applied to the root element
styleCSSPropertiesInline style applied to the root element

Timeline.Viewport Props

PropTypeDefaultDescription
childrenReact.ReactNodeRows and links, in any order
axisTimelineAxisAxis configuration: guides and stacked header levels
decorationsTimelineDecorationsDecorative layers: bands and markers
linkDefaultsTimelineLinkDefaultsShared defaults applied to all Timeline.Link nodes in this viewport
canvasWidthnumberFixed canvas width in pixels for horizontally scrollable timelines
stickyAxisbooleanfalsePins the axis to the top of the viewport during vertical scrolling
classNamestringAdditional CSS classes applied to the scroll viewport
styleCSSPropertiesInline style applied to the scroll viewport

Timeline.Row Props

PropTypeDefaultDescription
childrenReact.ReactNodeRow contents, typically Timeline.Interval elements
heightnumber32Row height in pixels
backgroundTimelineRowBackground | nullOptional background rendered in a dedicated layer, in front of bands but behind guide lines
classNamestringAdditional CSS classes applied to the row content container
styleCSSPropertiesInline style applied to the row content container

Timeline.Interval Props

PropTypeDefaultDescription
startDate | numberStart of the interval
endDate | numberEnd of the interval
childrenReact.ReactNodeRendered content for the interval
idstringStable id used by Timeline.Link to reference this interval
insetYnumber0Top and bottom inset in pixels within the row
classNamestringAdditional CSS classes applied to the positioned interval container
styleCSSPropertiesInline style applied to the positioned interval container
PropTypeDefaultDescription
fromstringSource Timeline.Interval id
tostringTarget Timeline.Interval id
fromAnchor"start" | "center" | "end""end"Source anchor used for routing
toAnchor"start" | "center" | "end""start"Target anchor used for routing
arrowbooleanOverrides the viewport-level linkDefaults.arrow
gapnumberOverrides the viewport-level linkDefaults.gap
strokeWidthnumberOptional stroke width for the link path
classNamestringAdditional CSS classes applied to the link SVG
styleCSSPropertiesInline style applied to the link SVG

Type Reference

TimelineAxis

Axis configuration for Timeline.Viewport.

FieldTypeDescription
guidesTimelineGuide[]Vertical boundary lines rendered in the axis and body
levelsTimelineAxisLevel[]Stacked header levels rendered above the body
classNamestringOptional class applied to the axis container

TimelineAxisLevel

A stacked axis level. Has a discriminated union kind field:

  • kind: "spans" — renders labeled time ranges (TimelineAxisSpan[])
  • kind: "ticks" — renders labeled point-in-time markers (TimelineAxisTick[])
FieldTypeDefaultDescription
kind"spans" | "ticks"Level rendering mode
itemsTimelineAxisSpan[] | TimelineAxisTick[]Items to render in this level
heightnumber28Height of this axis level in pixels
classNamestringOptional class applied to the level container

TimelineGuide

A vertical guide line rendered in both the axis and the body.

FieldTypeDescription
atDate | numberTime position for the guide line
keyReact.KeyOptional stable React key
axisClassNamestringOptional class for the axis portion of the guide
axisStyleCSSPropertiesOptional style for the axis portion of the guide
bodyClassNamestringOptional class for the body portion of the guide
bodyStyleCSSPropertiesOptional style for the body portion of the guide

TimelineDecorations

Decorative layers rendered by Timeline.Viewport.

FieldTypeDescription
bandsTimelineBand[]Background range highlights rendered behind rows
markersTimelineMarker[]Vertical markers rendered in the axis and/or body

TimelineBand

A decorative horizontal band rendered behind rows.

FieldTypeDescription
startDate | numberStart of the band
endDate | numberEnd of the band
keyReact.KeyOptional stable React key
colorstringOptional background color convenience prop
classNamestringOptional class applied to the band element
styleCSSPropertiesOptional inline style applied to the band

TimelineMarker

A decorative vertical marker line.

FieldTypeDefaultDescription
atDate | numberTime position for the marker
keyReact.KeyOptional stable React key
colorstringOptional line color convenience prop
labelReact.ReactNodeOptional marker label
placement"axis" | "body" | "both""body"Controls where the marker is rendered
classNamestringOptional class applied to the outer marker wrapper
lineClassNamestringOptional class applied to the marker line
labelClassNamestringOptional class applied to the marker label

TimelineLinkDefaults

Shared defaults for all Timeline.Link nodes inside one viewport.

FieldTypeDefaultDescription
routing"orthogonal""orthogonal"Link routing strategy
arrowbooleantrueWhether links end with an arrow marker
gapnumber16Horizontal gap in px used when routing out of/into items
strokeWidthnumberOptional default stroke width for link paths
classNamestringOptional class applied to each link SVG
styleCSSPropertiesOptional style applied to each link SVG

TimelineRowBackground

Background content for a row rendered in a dedicated layer (in front of bands, behind guides).

FieldTypeDescription
classNamestringOptional class applied to the background layer element
styleCSSPropertiesOptional style applied to the background layer element

Examples

Horizontal Scrolling

Use canvasWidth on Timeline.Viewport to enable horizontal scrolling:

tsx
<Timeline.Root start={projectStart} end={projectEnd}>
  <Timeline.Viewport canvasWidth={2400} axis={axis}>
    {rows}
  </Timeline.Viewport>
</Timeline.Root>

Sticky Axis

Pin the axis to the top during vertical scrolling with stickyAxis:

tsx
<Timeline.Root start={0} end={100}>
  <Timeline.Viewport stickyAxis axis={axis}>
    {rows}
  </Timeline.Viewport>
</Timeline.Root>

Use id on Timeline.Interval and Timeline.Link to draw dependency connectors:

tsx
<Timeline.Root start={0} end={100}>
  <Timeline.Viewport
    linkDefaults={{ style: { color: "var(--muted-foreground)" }, strokeWidth: 1.5 }}
  >
    <Timeline.Row height={40}>
      <Timeline.Interval id="task-a" start={10} end={40}>
        <div className="h-full rounded-md bg-primary" />
      </Timeline.Interval>
    </Timeline.Row>
    <Timeline.Row height={40}>
      <Timeline.Interval id="task-b" start={50} end={80}>
        <div className="h-full rounded-md bg-secondary" />
      </Timeline.Interval>
    </Timeline.Row>
    <Timeline.Link from="task-a" to="task-b" />
  </Timeline.Viewport>
</Timeline.Root>

Background Bands and Markers

Use decorations to add background highlights and vertical marker lines:

tsx
<Timeline.Viewport
  axis={axis}
  decorations={{
    bands: [
      {
        start: freezeStart,
        end: freezeEnd,
        color: "var(--destructive/10)",
        className: "astw:border-x astw:border-destructive/30",
      },
    ],
    markers: [
      {
        at: today,
        color: "var(--primary)",
        label: <span className="astw:text-xs astw:text-primary">Today</span>,
      },
    ],
  }}
>
  {rows}
</Timeline.Viewport>

Row Background

Use background on Timeline.Row to apply a background that respects guide lines:

tsx
<Timeline.Row height={40} background={{ style: { background: "var(--muted)" } }}>
  <Timeline.Interval start={10} end={35}>
    <div className="h-full rounded-md bg-primary" />
  </Timeline.Interval>
</Timeline.Row>