Timeline

A composable timeline view with draggable items, range headers, sidebar, and navigation tools.

Supported Features

  • Daily, monthly, and quarterly range views

  • Draggable and resizable timeline items

  • Auto-scroll to today's date on mount

  • Range navigation with previous/next jump buttons

  • "Today" indicator with tooltip

  • Optional sidebar with header and scrollable body

  • Marker creation via hover trigger

  • Deferred range transitions for smooth UI

Installation

pnpm add @notion-kit/ui

Anatomy

<TimelineProvider>
  <TimelineContent>
    <TimelineRangeHeader />
    <TimelineList>
      <TimelineRow.Root item={feature} onMove={handleMoveFeature}>
        <TimelineRow.Jump />
        <TimelineRow.Track>
          <TimelineRow.Resize direction="start" />
          <TimelineRow.Item>{feature.name}</TimelineRow.Item>
          <TimelineRow.Resize direction="end" />
        </TimelineRow.Track>
      </TimelineRow.Root>
    </TimelineList>
    <TimelineToolbar>
      <TimelineRangeSelect />
      <TimelineJumpTo />
    </TimelineToolbar>
    <TimelineToday />
  </TimelineContent>
  <TimelineSidebar>
    <TimelineSidebarHeader>
      <TimelineSidebarClose />
      {/* your header */}
    </TimelineSidebarHeader>
    <TimelineSidebarBody>
      {/* your body */}
    </TimelineSidebarBody>
  </TimelineSidebar>
</TimelineProvider>

Examples


Layout Only

A minimal timeline showing the range header, toolbar, and today indicator — without any items.

Without Sidebar

A full timeline with draggable items, context menus, range selection, and a marker creation trigger.

With Sidebar

A timeline with an attached sidebar panel listing all items, plus a header toolbar for opening/closing the sidebar.

API Reference

TimelineProvider

Root provider that manages timeline state, scroll position, and CSS variables.

PropTypeDefaultDescription
rangeTimelineRange"monthly"The active range granularity.
zoomnumber100Zoom level as a percentage.
startDatenumber | null-Override the timeline start date (timestamp).
endDatenumber | null-Override the timeline end date (timestamp).
sidebarWidthnumber-Controlled sidebar width in pixels. Auto-detected if omitted.
onAddItem(ts: number) => void-Handler called when clicking to add a new item.

TimelineContent

The main scrollable container that holds the range header, items, and tools.

TimelineList

The absolutely-positioned list container for timeline rows, placed below the range header.

TimelineRangeHeader

Renders the two-row header showing range labels (years/quarters) and sub-range labels (months/weeks/days). No additional props.

TimelineRow.Root

Owns one row's drag state and provides it to the compound parts. Omit onMove and the resize parts for a click-only row.

PropTypeDefaultDescription
item*TimelineFeature-The feature data used for row geometry and drag identity.
onMove(id: string, start: number, end: number | null) => void-Enables moving/resizing and receives the committed timestamp range.
childrenReact.ReactNode-Composed Jump, Track, Item, and optional Resize parts.

TimelineRow.Jump

Renders the off-screen navigation target used by Timeline jump controls. It reads the feature from TimelineRow.Root and takes no props.

TimelineRow.Track

Positions the item bar within one timeline row. Accepts standard <div> props.

TimelineRow.Item

Renders the full clickable card button and becomes the drag source when its root has onMove. Accepts standard button props, including onClick and children.

TimelineRow.Resize

Renders one draggable range edge. It is omitted automatically when the root has no onMove.

PropTypeDefaultDescription
direction*"start" | "end"-Selects the range edge to edit.

TimelineToolbar

A sticky toolbar container for placing controls like range select and jump-to.

TimelineHeaderToolbar

A pre-composed toolbar with sidebar trigger, range select, and jump-to buttons.

PropTypeDescription
onSidebarOpen() => voidHandler called when the sidebar open button is clicked.
onRangeChange(range: TimelineRange) => voidHandler called when the range is changed.

TimelineRangeSelect

A select dropdown for switching between range granularities.

PropTypeDescription
value*TimelineRangeThe currently selected range.
onChange(value: TimelineRange) => voidHandler called when the range is changed.

TimelineJumpTo

Navigation buttons for jumping to the previous/next range group and back to today.

TimelineToday

Renders a vertical red line and badge at today's date position.

GanttCreateMarkerTrigger

A hover-activated trigger that follows the cursor and creates a marker on click.

PropTypeDescription
onCreateMarker(ts: number) => voidHandler called with the timestamp of the click position.

TimelineSidebar

A sticky sidebar panel attached to the start edge of the timeline.

TimelineSidebarHeader

A sticky header inside the sidebar.

TimelineSidebarBody

A scrollable body area inside the sidebar.

TimelineSidebarClose

A button that hides the sidebar panel.

PropTypeDefaultDescription
descriptionstring"Hide table"Tooltip text for the close button.
onClick() => void-Handler called when clicked.

TimelineSidebarTrigger

A button that opens the sidebar panel.

PropTypeDefaultDescription
descriptionstring"Show table"Tooltip text for the trigger button.
onClick() => void-Handler called when clicked.

type TimelineRange

type TimelineRange = "daily" | "monthly" | "quarterly";

type TimelineFeature

PropTypeDescription
id*stringUnique identifier for the feature.
name*stringDisplay name of the feature.
startAt*numberStart timestamp in milliseconds.
endAt*number | nullEnd timestamp in milliseconds, or null for an open-ended item.