New in 0.7
Timeline
Try it
The Knight Lab timeline on every ground, mode and palette. Use the arrows, the markers or the zoom buttons.
on_change: —
Install
In React, Vue and Angular, SpTimeline is on its own subpath, @silverpoint/<framework>/timeline, and @knight-lab/timelinejs (^3.9.13) is an optional peer: install it only if you use the timeline, import the subpath only with it installed, and import its stylesheet before @silverpoint/grounds/timeline.css. The server renders the surface and an empty mount; TimelineJS builds in the browser, and if it cannot be loaded the mount shows your fallback and warns SP025.
In Reflex, sp_timeline is the npm SpTimeline, and @knight-lab/timelinejs is its npm dependency, installed when a page uses it: no Python extra is needed. The [timeline] extra is empty and timeline_available() always returns True; both are kept for older code.
In your code
npm install @knight-lab/timelinejsimport '@knight-lab/timelinejs/dist/css/timeline.css'; // TimelineJS's stylesheet first
import '@silverpoint/grounds/timeline.css';
import { SpTimeline } from '@silverpoint/react/timeline';
const story = {
title: { text: { headline: 'From silverpoint to silverpoint' } },
events: [
{ start_date: { year: 1484 }, text: { headline: 'Dürer at thirteen', text: '…' } },
{ start_date: { year: 1842 }, text: { headline: 'The cyanotype', text: '…' } },
],
eras: [{ start_date: { year: 1400 }, end_date: { year: 1600 }, text: { headline: 'Metalpoint' } }],
};
<SpTimeline
data={story}
height="560px"
palette={sepia} // from '@silverpoint/core/palettes'
inkedFrames // the ground's hand-drawn frames and tone tiles
onChange={(uniqueId) => console.log(uniqueId)} // the slide shown
fallback={<p>The timeline could not be loaded.</p>}
/>npm install @knight-lab/timelinejs<script setup lang="ts">
import '@knight-lab/timelinejs/dist/css/timeline.css';
import '@silverpoint/grounds/timeline.css';
import { SpTimeline } from '@silverpoint/vue/timeline';
const story = {
title: { text: { headline: 'From silverpoint to silverpoint' } },
events: [
{ start_date: { year: 1484 }, text: { headline: 'Dürer at thirteen', text: '…' } },
{ start_date: { year: 1842 }, text: { headline: 'The cyanotype', text: '…' } },
],
eras: [{ start_date: { year: 1400 }, end_date: { year: 1600 }, text: { headline: 'Metalpoint' } }],
};
</script>
<template>
<SpTimeline :data="story" height="560px" @change="(id) => console.log(id)">
<template #fallback><p>The timeline could not be loaded.</p></template>
</SpTimeline>
</template>npm install @knight-lab/timelinejs/* src/styles.css */
@import '@knight-lab/timelinejs/dist/css/timeline.css';
@import '@silverpoint/grounds/timeline.css';
// history.ts
import { Component } from '@angular/core';
import { SpTimeline, SpTimelineFallback } from '@silverpoint/angular/timeline';
const story = {
title: { text: { headline: 'From silverpoint to silverpoint' } },
events: [
{ start_date: { year: 1484 }, text: { headline: 'Dürer at thirteen', text: '…' } },
{ start_date: { year: 1842 }, text: { headline: 'The cyanotype', text: '…' } },
],
eras: [{ start_date: { year: 1400 }, end_date: { year: 1600 }, text: { headline: 'Metalpoint' } }],
};
@Component({
selector: 'app-history',
imports: [SpTimeline, SpTimelineFallback],
template: `
<sp-timeline [data]="story" height="560px" (change)="slide = $event">
<ng-template spFallback><p>The timeline could not be loaded.</p></ng-template>
</sp-timeline>
`,
})
export class History {
protected slide: string | undefined;
protected readonly story = story;
}pip install reflex-silverpoint-reactfrom reflex_silverpoint_react import sp_timeline
DATA = {
"title": {"text": {"headline": "From silverpoint to silverpoint"}},
"events": [
{"start_date": {"year": 1484}, "text": {"headline": "Dürer at thirteen", "text": "…"}},
{"start_date": {"year": 1842}, "text": {"headline": "The cyanotype", "text": "…"}},
],
"eras": [
{"start_date": {"year": 1400}, "end_date": {"year": 1600}, "text": {"headline": "Metalpoint"}},
],
}
sp_timeline(
DATA, # TimelineJS data (or a TimelineData of reflex-knightlab-timeline)
height=560,
ground="silverpoint",
substrate="cream",
mode="ink",
palette="sepia",
inked_frames=True, # the ground's hand-drawn frames and tone tiles
on_change=State.on_slide, # the unique_id of the slide shown
)Two layers: the skin and the hand
- The skin replaces TimelineJS's colours, type and rules with the ground's
--sp-properties: the substrate, the inks, EB Garamond, hairline rules, eras hatched by density, the current marker heightened. - The hand reads the ground's own frame and tone masks from hidden probes and lays them on the markers, eras and menubar, so they are drawn with the same pieces as the Sp components.
inked_frames=Falsekeeps the skin only;precision,cyanotypeand forced colours fall back to exact rules by themselves.
Props and events
The names below are Reflex's; in JavaScript they are camelCase (inkedFrames, onNavNext in React, @nav-next in Vue, (navNext) in Angular), height is a CSS length (default '600px'), and label names the region (the title's headline when omitted).
| Prop | Default | |
|---|---|---|
data | — | TimelineJS data (title, events, eras, scale), a TimelineData, or a state var. |
options | {} | TimelineJS options; font and theme are ignored (the skin sets both). |
height | 600 | Height of the whole timeline (px or a CSS length). |
inked_frames | True | Lays the ground's hand-drawn frames and tone tiles. |
card | True | Frames the whole timeline as a card. |
ground, substrate, mode, palette, seed | — | The surface props. |
on_change | — | The unique_id of the slide shown. |
on_loaded | — | TimelineJS's loaded payload. |
on_nav_next, on_nav_previous, on_zoom_in, on_zoom_out, on_back_to_start | — | The timeline's navigation. |
sp_timeline_list.