Timeline
Basic Configuration
The Timeline component has been designed to work together with XY Container. The minimal Timeline configuration looks like:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisXYContainer, VisTimeline } from '@unovis/react'
function Component(props) {
const data: TimeDataRecord[] = props.data
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
return (
<VisXYContainer data={data}>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
/>
</VisXYContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: TimeDataRecord[];
lineDuration = (d: TimeDataRecord) => d.length
lineRow = (d: TimeDataRecord) => d.type
x = (d: TimeDataRecord) => d.timestamp
}
<vis-xy-container [data]="data">
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
></vis-timeline>
</vis-xy-container>
<script lang='ts'>
import { VisXYContainer, VisTimeline } from '@unovis/svelte'
export let data: TimeDataRecord[]
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
</script>
<VisXYContainer {data}>
<VisTimeline {lineDuration} {lineRow} {x}/>
</VisXYContainer>
<script setup lang="ts">
import { VisXYContainer, VisTimeline } from '@unovis/vue'
const props = defineProps<{ data: TimeDataRecord[] }>()
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
</script>
<template>
<VisXYContainer :data="data">
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
/>
</VisXYContainer>
</template>
import { VisXYContainer, VisTimeline } from '@unovis/solid'
function Component(props) {
const data: TimeDataRecord[] = () => props.data
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
return (
<VisXYContainer data={data()}>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
/>
</VisXYContainer>
)
}
import { XYContainer, Timeline } from '@unovis/ts'
import { data, TimeDataRecord } from './data'
const container = new XYContainer<TimeDataRecord>(node, {
components: [
new Timeline<TimeDataRecord>({
lineDuration: (d: TimeDataRecord) => d.length,
lineRow: (d: TimeDataRecord) => d.type,
x: (d: TimeDataRecord) => d.timestamp
})
]
}, data)
where each record should provide at least the following information:
type TimeDataRecord = {
timestamp: Date; // Position on the X axis. Can be `number` or `Date`
duration: number; // Length of the line in X axis values, i.e. milliseconds if you use `Date`
name: string; // The row it will be displayed in
}
Wire these up via the lineDuration and lineRow accessors (along with x for the timestamp).
The legacy type and length properties on the Timeline component are deprecated.
Use lineRow and lineDuration instead.
Row Labels
Enable the showRowLabels property to display row types along the vertical axis. You can control
the label width with rowLabelWidth (fixed) and rowMaxLabelWidth (maximum) properties.
The showLabels, labelWidth, and maxLabelWidth properties are deprecated. Use showRowLabels,
rowLabelWidth, and rowMaxLabelWidth instead.
Like other XY components, labeling data along the horizontal axis can be accomplished by adding an Axis component to your container. See following example which displays labeled Timeline alongside a labeled X Axis:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYContainer data={data}>
<VisAxis type="x" tickFormat={tickFormat}/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
</VisXYContainer>
<vis-xy-container [data]="data">
<vis-axis type="x" [tickFormat]="tickFormat"></vis-axis>
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[showRowLabels]="true"
></vis-timeline>
</vis-xy-container>
<VisXYContainer {data}>
<VisAxis type="x" {tickFormat}/>
<VisTimeline {lineDuration} {lineRow} {x} showRowLabels={true}/>
</VisXYContainer>
<VisXYContainer :data="data">
<VisAxis type="x" :tickFormat="tickFormat" />
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:showRowLabels="true"
/>
</VisXYContainer>
<VisXYContainer data={data}>
<VisAxis type="x" tickFormat={tickFormat}/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
</VisXYContainer>
const container = new XYContainer<TimeDataRecord>(node, {
xAxis: new Axis({ type: "x", tickFormat }),
components: [new Timeline({ lineDuration, lineRow, x, showRowLabels: true })]
}, data)
Since Timeline groups vertical data in an ordinal fashion, adding a Y axis here is not recommended.
Label Text Align
Use the rowLabelTextAlign property to control the horizontal alignment of row labels:
TextAlign.Left, TextAlign.Center, or TextAlign.Right (default).
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
rowLabelTextAlign="left"
/>
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[showRowLabels]="true"
rowLabelTextAlign="left"
></vis-timeline>
<VisTimeline
{lineDuration}
{lineRow}
{x}
showRowLabels={true}
rowLabelTextAlign="left"
/>
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:showRowLabels="true"
rowLabelTextAlign="left"
/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
rowLabelTextAlign="left"
/>
const timeline = new Timeline<TimeDataRecord>({
lineDuration,
lineRow,
x,
showRowLabels: true,
rowLabelTextAlign: "left"
})
Label Width
Set a fixed label width with rowLabelWidth or a maximum width with rowMaxLabelWidth.
Labels longer than the specified value will be trimmed.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
rowLabelWidth={60}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
<vis-timeline
[rowLabelWidth]="60"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[showRowLabels]="true"
></vis-timeline>
<VisTimeline
rowLabelWidth={60}
{lineDuration}
{lineRow}
{x}
showRowLabels={true}
/>
<VisTimeline
:rowLabelWidth="60"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:showRowLabels="true"
/>
<VisTimeline
rowLabelWidth={60}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
const timeline = new Timeline<TimeDataRecord>({
rowLabelWidth: 60,
lineDuration,
lineRow,
x,
showRowLabels: true
})
Label Trim Mode
When labels exceed the available width, they'll be trimmed. Use the rowLabelTrimMode property to control
where the trimming occurs: TrimMode.Start, TrimMode.Middle (default), or TrimMode.End.
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
rowLabelWidth={70}
rowLabelTrimMode="end"
/>
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[showRowLabels]="true"
[rowLabelWidth]="70"
rowLabelTrimMode="end"
></vis-timeline>
<VisTimeline
{lineDuration}
{lineRow}
{x}
showRowLabels={true}
rowLabelWidth={70}
rowLabelTrimMode="end"
/>
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:showRowLabels="true"
:rowLabelWidth="70"
rowLabelTrimMode="end"
/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
rowLabelWidth={70}
rowLabelTrimMode="end"
/>
const timeline = new Timeline<TimeDataRecord>({
lineDuration,
lineRow,
x,
showRowLabels: true,
rowLabelWidth: 70,
rowLabelTrimMode: "end"
})
Label Margin
Use the rowLabelMargin property to set the spacing (in pixels) between the row labels and the timeline content.
You can also provide a [left, right] tuple to control spacing on both sides of the label independently:
- The first value sets the left margin (space from the container edge or row icon to the label)
- The second value sets the right margin (space between the label and the timeline content)
rowLabelMargin: [10, 5] // 10px left, 5px right
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
rowLabelMargin={5}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
<vis-timeline
[rowLabelMargin]="5"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[showRowLabels]="true"
></vis-timeline>
<VisTimeline
rowLabelMargin={5}
{lineDuration}
{lineRow}
{x}
showRowLabels={true}
/>
<VisTimeline
:rowLabelMargin="5"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:showRowLabels="true"
/>
<VisTimeline
rowLabelMargin={5}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
showRowLabels={true}
/>
const timeline = new Timeline<TimeDataRecord>({
rowLabelMargin: 5,
lineDuration,
lineRow,
x,
showRowLabels: true
})
Label Style
Use rowLabelStyle to apply custom CSS styles to row labels. It accepts an object with CSS property-value pairs
or an accessor function for per-label styling.
rowLabelStyle: { 'font-weight': 'bold', 'fill': '#333' }
Label Formatter
Use rowLabelFormatter to customize the displayed label text. It receives the row key, the row's data items, and the row index.
rowLabelFormatter: (key: string, items: Datum[], i: number) => `${key} (${items.length})`
Icon
Use the rowIcon property to display an icon before each row label. The function receives the row key, items, and index,
and should return a TimelineRowIcon object or undefined.
type TimelineRowIcon = {
href: string; // SVG icon href (defined in container's svgDefs)
size: number;
color: string;
}
Row Configuration
Alternating row colors
For easier readability, each row's background color alternates among two colors by default. To display a single
background color across all rows, disable the alternatingRowColors property:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
alternatingRowColors={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
/>
<vis-timeline
[alternatingRowColors]="true"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
></vis-timeline>
<VisTimeline alternatingRowColors={true} {lineDuration} {lineRow} {x}/>
<VisTimeline
:alternatingRowColors="true"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
/>
<VisTimeline
alternatingRowColors={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
/>
const timeline = new Timeline<TimeDataRecord>({
alternatingRowColors: true,
lineDuration,
lineRow,
x
})
Row Height
Use the rowHeight property to adjust the size of each row.
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
rowHeight={50}
/>
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[rowHeight]="50"
></vis-timeline>
<VisTimeline {lineDuration} {lineRow} {x} rowHeight={50}/>
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:rowHeight="50"
/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
rowHeight={50}
/>
const timeline = new Timeline<TimeDataRecord>({
lineDuration,
lineRow,
x,
rowHeight: 50
})
Filling empty vertical space
When the timeline container is taller than the combined height of all rows, rowFillEmptySpace (default: true) stretches row layout so the rows use the extra space. Set it to false if you prefer rows to stay compact at the top and leave the remainder of the container empty.
Line Configuration
Line Cap
By default, lines have squared ends. You can give your lines a rounded appearance by setting lineCap property to true.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
/>
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[lineCap]="true"
></vis-timeline>
<VisTimeline {lineDuration} {lineRow} {x} lineCap={true}/>
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:lineCap="true"
/>
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
/>
const timeline = new Timeline<TimeDataRecord>({
lineDuration,
lineRow,
x,
lineCap: true
})
Showing empty segments
Set showEmptySegments to true if you want to display lines that are undefined or too small to see.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
showEmptySegments={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
/>
<vis-timeline
[showEmptySegments]="true"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[lineCap]="true"
></vis-timeline>
<VisTimeline
showEmptySegments={true}
{lineDuration}
{lineRow}
{x}
lineCap={true}
/>
<VisTimeline
:showEmptySegments="true"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:lineCap="true"
/>
<VisTimeline
showEmptySegments={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
/>
const timeline = new Timeline<TimeDataRecord>({
showEmptySegments: true,
lineDuration,
lineRow,
x,
lineCap: true
})
Empty segments positioning
When both showEmptySegments and lineCap are set to true, you can control the positioning of small segments using
the showEmptySegmentsCorrectPosition property. When set to true (default), small segments will be centered at their
actual position. When set to false, small segments will be aligned to the left of their position.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
showEmptySegmentsCorrectPosition={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
showEmptySegments={true}
/>
<vis-timeline
[showEmptySegmentsCorrectPosition]="true"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[lineCap]="true"
[showEmptySegments]="true"
></vis-timeline>
<VisTimeline
showEmptySegmentsCorrectPosition={true}
{lineDuration}
{lineRow}
{x}
lineCap={true}
showEmptySegments={true}
/>
<VisTimeline
:showEmptySegmentsCorrectPosition="true"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:lineCap="true"
:showEmptySegments="true"
/>
<VisTimeline
showEmptySegmentsCorrectPosition={true}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
lineCap={true}
showEmptySegments={true}
/>
const timeline = new Timeline<TimeDataRecord>({
showEmptySegmentsCorrectPosition: true,
lineDuration,
lineRow,
x,
lineCap: true,
showEmptySegments: true
})
Line Width
You can also change the line thickness with the lineWidth property, which determines how much
vertical space each Timeline item occupies.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisTimeline
lineWidth={10}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
rowHeight={50}
/>
<vis-timeline
[lineWidth]="10"
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[rowHeight]="50"
></vis-timeline>
<VisTimeline
lineWidth={10}
{lineDuration}
{lineRow}
{x}
rowHeight={50}
/>
<VisTimeline
:lineWidth="10"
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:rowHeight="50"
/>
<VisTimeline
lineWidth={10}
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
rowHeight={50}
/>
const timeline = new Timeline<TimeDataRecord>({
lineWidth: 10,
lineDuration,
lineRow,
x,
rowHeight: 50
})
Line Cursor
Use the lineCursor property to set a custom CSS cursor when hovering over a timeline line.
The cursor property is deprecated. Use lineCursor instead.
Line Icons
You can display icons at the start and/or end of each timeline line using SVG symbols defined in the
container's svgDefs.
| Property | Description |
|---|---|
lineStartIcon / lineEndIcon | SVG icon href accessor |
lineStartIconColor / lineEndIconColor | Icon color accessor |
lineStartIconSize / lineEndIconSize | Icon size accessor |
lineStartIconArrangement / lineEndIconArrangement | Icon positioning relative to the line: Arrangement.Inside (default), Arrangement.Outside, Arrangement.Start, Arrangement.Middle, or Arrangement.End |
Arrows
Use the arrows property to draw connecting arrows between timeline lines. Each arrow is defined as a TimelineArrow object:
type TimelineArrow = {
id?: string;
xSource?: number; // X position of arrow start (defaults to source line's end)
xTarget?: number; // X position of arrow end (defaults to target line's start)
xSourceOffsetPx?: number; // Horizontal offset of the source in pixels
xTargetOffsetPx?: number; // Horizontal offset of the target in pixels
lineSourceId: string; // Id of the source line element
lineTargetId: string; // Id of the target line element
lineSourceMarginPx?: number; // Margin between source line and arrow in pixels
lineTargetMarginPx?: number; // Margin between target line and arrow in pixels
arrowHeadLength?: number; // Arrowhead length in pixels (default: 8)
arrowHeadWidth?: number; // Arrowhead width in pixels (default: 6)
}
The lineSourceId and lineTargetId correspond to the values returned by the id accessor on your data items.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
function Component(props) {
const data: TimeDataRecord[] = props.data
const arrows = [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
const x = (d: TimeDataRecord) => d.timestamp
const id = (d: TimeDataRecord) => d.id
const lineRow = (d: TimeDataRecord) => d.name
const lineDuration = (d: TimeDataRecord) => d.duration
return (
<VisTimeline
x={x}
id={id}
lineRow={lineRow}
lineDuration={lineDuration}
lineCap={true}
rowHeight={35}
showRowLabels={true}
arrows={arrows}
/>
)
}
@Component({
template: `
<vis-timeline
[x]="x"
[id]="id"
[lineRow]="lineRow"
[lineDuration]="lineDuration"
[lineCap]="true"
[rowHeight]="35"
[showRowLabels]="true"
[arrows]="arrows"
></vis-timeline>
`
})
export class Component {
@Input data: TimeDataRecord[];
arrows = [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
x = (d: TimeDataRecord) => d.timestamp
id = (d: TimeDataRecord) => d.id
lineRow = (d: TimeDataRecord) => d.name
lineDuration = (d: TimeDataRecord) => d.duration
}
<script lang='ts'>
import { VisXYContainer, VisTimeline } from '@unovis/svelte'
export let data: TimeDataRecord[]
const arrows = [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
const x = (d: TimeDataRecord) => d.timestamp
const id = (d: TimeDataRecord) => d.id
const lineRow = (d: TimeDataRecord) => d.name
const lineDuration = (d: TimeDataRecord) => d.duration
</script>
<VisTimeline
{x}
{id}
{lineRow}
{lineDuration}
lineCap={true}
rowHeight={35}
showRowLabels={true}
{arrows}
/>
<script setup lang="ts">
import { VisXYContainer, VisTimeline } from '@unovis/vue'
const props = defineProps<{ data: TimeDataRecord[] }>()
const arrows = [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
const x = (d: TimeDataRecord) => d.timestamp
const id = (d: TimeDataRecord) => d.id
const lineRow = (d: TimeDataRecord) => d.name
const lineDuration = (d: TimeDataRecord) => d.duration
</script>
<template>
<VisTimeline
:x="x"
:id="id"
:lineRow="lineRow"
:lineDuration="lineDuration"
:lineCap="true"
:rowHeight="35"
:showRowLabels="true"
:arrows="arrows"
/>
</template>
function Component(props) {
const data: TimeDataRecord[] = () => props.data
const arrows = [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
const x = (d: TimeDataRecord) => d.timestamp
const id = (d: TimeDataRecord) => d.id
const lineRow = (d: TimeDataRecord) => d.name
const lineDuration = (d: TimeDataRecord) => d.duration
return (
<VisTimeline
x={x}
id={id}
lineRow={lineRow}
lineDuration={lineDuration}
lineCap={true}
rowHeight={35}
showRowLabels={true}
arrows={arrows}
/>
)
}
const timeline = new Timeline<TimeDataRecord>({
x: (d: TimeDataRecord) => d.timestamp,
id: (d: TimeDataRecord) => d.id,
lineRow: (d: TimeDataRecord) => d.name,
lineDuration: (d: TimeDataRecord) => d.duration,
lineCap: true,
rowHeight: 35,
showRowLabels: true,
arrows: [{ lineSourceId: 'item-0', lineTargetId: 'item-1', xSource: ... }, ...]
})
Events
Scrolling
You can provide a callback to the onScroll property, which accepts a function of type:
type onScroll = (n: number) => void
where n is equal to the distance scrolled from the top of the timeline (in pixels).
See the following example, where onScroll updates the xAxis label:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
function Component(props) {
const data: TimeDataRecord[] = props.data
const onScroll = (n: number) => setAxisLabel(`${n}px from the top`)
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
return (
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
onScroll={onScroll}
/>
)
}
@Component({
template: `
<vis-timeline
[lineDuration]="lineDuration"
[lineRow]="lineRow"
[x]="x"
[onScroll]="onScroll"
></vis-timeline>
`
})
export class Component {
@Input data: TimeDataRecord[];
onScroll = (n: number) => setAxisLabel(`${n}px from the top`)
lineDuration = (d: TimeDataRecord) => d.length
lineRow = (d: TimeDataRecord) => d.type
x = (d: TimeDataRecord) => d.timestamp
}
<script lang='ts'>
import { VisXYContainer, VisTimeline } from '@unovis/svelte'
export let data: TimeDataRecord[]
const onScroll = (n: number) => setAxisLabel(`${n}px from the top`)
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
</script>
<VisTimeline {lineDuration} {lineRow} {x} {onScroll}/>
<script setup lang="ts">
import { VisXYContainer, VisTimeline } from '@unovis/vue'
const props = defineProps<{ data: TimeDataRecord[] }>()
const onScroll = (n: number) => setAxisLabel(`${n}px from the top`)
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
</script>
<template>
<VisTimeline
:lineDuration="lineDuration"
:lineRow="lineRow"
:x="x"
:onScroll="onScroll"
/>
</template>
function Component(props) {
const data: TimeDataRecord[] = () => props.data
const onScroll = (n: number) => setAxisLabel(`${n}px from the top`)
const lineDuration = (d: TimeDataRecord) => d.length
const lineRow = (d: TimeDataRecord) => d.type
const x = (d: TimeDataRecord) => d.timestamp
return (
<VisTimeline
lineDuration={lineDuration}
lineRow={lineRow}
x={x}
onScroll={onScroll}
/>
)
}
const timeline = new Timeline<TimeDataRecord>({
lineDuration: (d: TimeDataRecord) => d.length,
lineRow: (d: TimeDataRecord) => d.type,
x: (d: TimeDataRecord) => d.timestamp,
onScroll: (n: number) => setAxisLabel(`${n}px from the top`)
})
Custom cursor for hover events
You can set a custom cursor when hovering over a line using the lineCursor property. It'll only be active if you've defined events for [Timeline.selectors.line]:
More Events
import { Timeline } from '@unovis/ts'
const events = {
[Timeline.selectors.background]: {
wheel: () => { ... },
},
[Timeline.selectors.line]: {
click: () => { ... },
}
[Timeline.selectors.label]: {
mouseover: () => { ... }
}
}
CSS Variables
The Timeline component supports additional styling via CSS variables:
All supported CSS variables and their default values
--vis-timeline-row-even-fill-color: #FFFFFF;
--vis-timeline-row-odd-fill-color: #F7FAFC;
--vis-timeline-row-background-opacity: 1;
--vis-timeline-scrollbar-background-color: #E6E9F3;
--vis-timeline-scrollbar-color: #9EA7B8;
--vis-timeline-label-font-size: 12px;
--vis-timeline-label-color: #6C778C;
--vis-timeline-label-user-select: none;
--vis-timeline-label-pointer-events: all;
--vis-timeline-arrow-color: #6C778C;
--vis-timeline-arrow-stroke-width: 1.5;
--vis-timeline-cursor: default;
--vis-timeline-line-color: var(--vis-color-main);
--vis-timeline-line-stroke-color: undefined;
--vis-timeline-line-stroke-width: 0;
--vis-timeline-line-hover-stroke-width: 0;
--vis-timeline-line-hover-stroke-color: #6C778C;
--vis-timeline-row-icon-cursor: default;
--vis-dark-timeline-row-even-fill-color: #292B34;
--vis-dark-timeline-row-odd-fill-color: #333742;
--vis-dark-timeline-scrollbar-background-color: #292B34;
--vis-dark-timeline-scrollbar-color: #6C778C;
--vis-dark-timeline-label-color: #EFF5F8;
--vis-dark-timeline-arrow-color: #EFF5F8;
--vis-dark-timeline-line-hover-stroke-color: #EFF5F8;
Component Props
| Name | Type | Description |
|---|---|---|
| * required property |