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.
npm i @observablehq/plotpnpm add @observablehq/plotyarn add @observablehq/plotQuick Start
Section titled “Quick Start”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 chartsdocument.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>Available Components
Section titled “Available Components”Charts fall into two groups based on data source:
- Analysis charts — SpeedTimeline, CompositionTimeline, RhythmHeatmap, PauseDistribution. Consume a
SessionAnalysisfromgetAnalysis()(requires WASM). - Event-detail charts — Sparkline, DocumentGrowth, DocumentRibbon, EditWaterfall, CorrectionsBubble. Consume raw
WriteTrackDataSchemafromgetData()(no WASM needed).
Theming
Section titled “Theming”Charts use CSS custom properties for colors, fonts, and spacing. They automatically adapt to dark/light themes via three mechanisms (in priority order):
themeattribute on the element:<wt-speed-timeline theme="light">data-themeattribute on an ancestor:<body data-theme="light">prefers-color-schememedia query (automatic)
Custom Properties
Section titled “Custom Properties”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 */}| Property | Default (dark) | Default (light) | Used for |
|---|---|---|---|
--wt-color-primary | #fbbf24 | #f59e0b | Lines, fills, bars |
--wt-color-secondary | #22d3ee | #06b6d4 | Paste events, accents |
--wt-color-bg | #111113 | #ffffff | Component background |
--wt-color-surface | #1a1a1d | #f5f5f4 | Panel backgrounds |
--wt-color-text | #fafafa | #1a1a1a | Axis labels, text |
--wt-color-text-muted | #a1a1aa | #6b7280 | Secondary labels |
--wt-color-border | #27272a | #e5e5e5 | Grid lines, rules |
--wt-font-data | JetBrains Mono | JetBrains Mono | Chart labels |
--wt-font-ui | DM Sans | DM Sans | Legends, UI text |
Sizing
Section titled “Sizing”Control chart dimensions with CSS custom properties. These take priority over clientWidth/clientHeight:
| Property | Description |
|---|---|
--wt-chart-width | SVG width in pixels (e.g. 800px) |
--wt-chart-height | SVG height in pixels (e.g. 200px) |
Chart-Specific Properties
Section titled “Chart-Specific Properties”Individual charts expose additional custom properties for fine-grained color control:
wt-edit-beeswarm — keystroke colors:
| Property | Default | Used for |
|---|---|---|
--wt-beeswarm-insert | #22c55e | Typed keystrokes |
--wt-beeswarm-delete | muted | Delete keystrokes |
--wt-beeswarm-paste | secondary | Paste events |
--wt-beeswarm-cut | #f97316 | Cut events |
wt-corrections-bubble — edit type colors:
| Property | Default | Used for |
|---|---|---|
--wt-bubble-insert | #22c55e | Insert runs |
--wt-bubble-delete | #ef4444 | Delete runs |
--wt-bubble-paste | secondary | Paste events |
--wt-bubble-cut | #f97316 | Cut events |
wt-edit-waterfall — cut event color:
| Property | Default | Used for |
|---|---|---|
--wt-color-cut | #f97316 | Cut event dots |
Declarative Usage
Section titled “Declarative Usage”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).
Extract Functions
Section titled “Extract Functions”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.