Skip to content

Visualization

WriteTrack ships chart components as web components powered by Observable Plot. Each chart is a custom element with Shadow DOM encapsulation, responsive sizing, and dark/light theme support.

Terminal window
npm i @observablehq/plot
import { SpeedTimeline, CompositionTimeline } from 'writetrack/viz';
// Register the custom elements (call once)
SpeedTimeline.register();
CompositionTimeline.register();
// After running analysis:
const analysis = await tracker.getAnalysis();
// Pass analysis data to the charts
document.querySelector('wt-speed-timeline').setData(analysis);
document.querySelector('wt-composition-timeline').setData(analysis);
<!-- Add the elements to your page -->
<wt-speed-timeline style="width: 100%; height: 200px;"></wt-speed-timeline>
<wt-composition-timeline
style="width: 100%; height: 80px;"
></wt-composition-timeline>

Charts fall into two groups based on data source:

Charts use CSS custom properties for colors, fonts, and spacing. They automatically adapt to dark/light themes via three mechanisms (in priority order):

  1. theme attribute on the element: <wt-speed-timeline theme="light">
  2. data-theme attribute on an ancestor: <body data-theme="light">
  3. prefers-color-scheme media query (automatic)

Override these on the host element or a parent container:

wt-speed-timeline {
--wt-color-primary: #3b82f6; /* Chart line/fill color */
--wt-color-secondary: #22d3ee; /* Accent color (paste events) */
--wt-color-text: #fafafa; /* Axis labels */
--wt-color-text-muted: #a1a1aa; /* Secondary text */
--wt-color-border: #27272a; /* Grid lines */
--wt-font-data: 'JetBrains Mono', monospace; /* Data labels */
}
PropertyDefault (dark)Default (light)Used for
--wt-color-primary#fbbf24#f59e0bLines, fills, bars
--wt-color-secondary#22d3ee#06b6d4Paste events, accents
--wt-color-bg#111113#ffffffComponent background
--wt-color-surface#1a1a1d#f5f5f4Panel backgrounds
--wt-color-text#fafafa#1a1a1aAxis labels, text
--wt-color-text-muted#a1a1aa#6b7280Secondary labels
--wt-color-border#27272a#e5e5e5Grid lines, rules
--wt-font-dataJetBrains MonoJetBrains MonoChart labels
--wt-font-uiDM SansDM SansLegends, UI text

Control chart dimensions with CSS custom properties. These take priority over clientWidth/clientHeight:

PropertyDescription
--wt-chart-widthSVG width in pixels (e.g. 800px)
--wt-chart-heightSVG height in pixels (e.g. 200px)

Individual charts expose additional custom properties for fine-grained color control:

wt-edit-beeswarm — keystroke colors:

PropertyDefaultUsed for
--wt-beeswarm-insert#22c55eTyped keystrokes
--wt-beeswarm-deletemutedDelete keystrokes
--wt-beeswarm-pastesecondaryPaste events
--wt-beeswarm-cut#f97316Cut events

wt-corrections-bubble — edit type colors:

PropertyDefaultUsed for
--wt-bubble-insert#22c55eInsert runs
--wt-bubble-delete#ef4444Delete runs
--wt-bubble-pastesecondaryPaste events
--wt-bubble-cut#f97316Cut events

wt-edit-waterfall — cut event color:

PropertyDefaultUsed for
--wt-color-cut#f97316Cut event dots

Charts also accept data via a data attribute (JSON string), useful for server-rendered pages:

<wt-speed-timeline data="..." style="width: 100%; height: 200px;">
</wt-speed-timeline>

The attribute value should be a JSON-serialized SessionAnalysis (for analysis charts) or WriteTrackDataSchema (for event-detail charts).

Each chart exports a standalone data-extraction function so you can use the data without the web components:

import {
extractSeries, // Sparkline: raw capture → [timestamps[], speeds[]]
extractSpeedData, // Speed timeline: analysis → SpeedPoint[]
extractSegments, // Composition: analysis → SegmentDatum[]
extractPasteMarkers, // Composition: analysis → PasteDatum[]
extractRhythmPairs, // Rhythm heatmap: analysis → RhythmPoint[]
extractPauseHistogram, // Pause distribution: analysis → PauseBin[]
extractGrowthData, // Document growth: raw capture → GrowthPoint[]
extractRibbonData, // Document ribbon: raw capture → RibbonDatum[]
extractWaterfallData, // Edit waterfall: raw capture → WaterfallData
extractCorrectionBubbles, // Corrections bubble: raw capture → BubbleDatum[]
} from 'writetrack/viz';

The BaseChart class is also exported for building custom chart components.