JavaScript Timeline
Pico Library
The LemonadeJS JavaScript Timeline is a framework-agnostic plugin designed for timeline creation, supporting Vue, React, and Angular integration. It facilitates the construction of logs, event timelines, and roadmaps, providing options for customization such as color adjustments, content modification, and control over point positioning. The plugin includes features for automatically grouping events by month and navigation controls, aiding in organizing and displaying timeline data.
Documentation
Installation
npm install @lemonadejs/timeline
Configuration Options
Initialize the timeline with these settings to tailor the plugin to your specific needs:
Attribute | Type | Description |
---|---|---|
data | Item[] | An array of items to be displayed. Each item should follow the structure defined in the 'Item Properties' section. |
type? | string | There are default and monthly types. The latter will create a navigation per month and group all items. |
align? | string | Align the bullet points. Accepted values include "left", "right", "top", and "bottom". Default: "left" . |
message? | string | Will show when no data to display |
order? | string | Accepted values are 'asc' for ascending and 'desc' for descending order. |
width? | number | Determines the width of the javascript timeline container. |
height? | number | Determines the height of the javascript timeline container. |
Entry Attributes
Define each timeline event with these specific properties to customize its appearance and behavior:
Attribute | Description |
---|---|
date?: string | A date associated with the item, providing chronological information. |
title?: string | Title for the item. |
subtitle?: string | Sub caption for the item. |
description?: string | Item description. |
borderColor?: string | Border color |
borderStyle?: string | Define the style of the item's border, such as "solid," "dashed," or "dotted." |
Event Handling
Utilize this event to monitor user interactions, enabling data synchronization with the server:
Event | Trigger |
---|---|
onupdate? | Called when the items are updated. |
Examples
This section illustrates practical applications of the JavaScript timeline plugin, highlighting customization techniques for style and functionality to align with specific project objectives.
See more examples on https://codesandbox.io/p/sandbox/frosty-babycat-cjcwrk
Styling Attributes
Customize the visual aspects such as position, border style, and color schemes by setting the corresponding attributes during the initialization phase as demonstrated below:
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/style.min.css" />
<div id="root"></div>
<script>
const root = document.getElementById("root")
Timeline(root, {
data: [
{
title: "Issue Identification",
date: new Date(2022, 6, 1),
},
{
title: "Root Cause Analysis",
date: new Date(2022, 6, 2),
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 3),
borderColor: '#808000',
borderStyle: 'dashed',
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 4),
}
],
align: 'left'
})
</script>
</html>
import lemonade from 'lemonadejs'
import Timeline from '@lemonadejs/timeline';
import '@lemonadejs/timeline/dist/style.css';
export default function App() {
const self = this;
self.data = [
{
title: "Issue Identification",
date: new Date(2022, 6, 1),
},
{
title: "Root Cause Analysis",
date: new Date(2022, 6, 2),
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 3),
borderColor: '#808000',
borderStyle: 'dashed',
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 4),
}
];
return `<Timeline :data="self.data" align="left" /></div>`
}
import React, { useRef } from 'react';
import Timeline from '@lemonadejs/timeline/dist/react';
export default function App() {
const myRef = useRef();
self.data = [
{
title: "Issue Identification",
date: new Date(2022, 6, 1),
},
{
title: "Root Cause Analysis",
date: new Date(2022, 6, 2),
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 3),
borderColor: '#808000',
borderStyle: 'dashed',
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 4),
}
];
return (<div>
<Timeline ref={myRef} data={data} align="left" />
</div>);
}
<template>
<Timeline :data="data" align="left" />
</template>
<script>
import Timeline from '@lemonadejs/timeline/dist/vue'
export default {
name: 'App',
components: {
Timeline
},
data() {
return {
data: [
{
title: "Issue Identification",
date: new Date(2022, 6, 1),
},
{
title: "Root Cause Analysis",
date: new Date(2022, 6, 2),
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 3),
borderColor: '#808000',
borderStyle: 'dashed',
},
{
title: "Implementation of Solution",
date: new Date(2022, 6, 4),
}
]
};
},
}
</script>
<style>
</style>
Positioning Options
Configure the placement of the timeline on the page by choosing from four positions: left, right, bottom, or top. Adjustments can also be made programmatically, as shown in the following example:
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/style.min.css" />
<label for="dropdown">Choose a position to align:</label>
<select id="dropdown">
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
<div id="root"></div>
<script>
const root = document.getElementById("root")
const dropdown = document.getElementById("dropdown")
const tml = Timeline(root, {
data: [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
],
})
dropdown.addEventListener('change', (e) => {
tml.align = e.target.value
})
</script>
</html>
import lemonade from 'lemonadejs'
import Timeline from '@lemonadejs/timeline';
import '@lemonadejs/timeline/dist/style.css';
export default function App() {
const self = this;
self.data = [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
]
self.align = function(e) {
self.ref.align = e.target.value;
}
return `<div>
<label>Choose a position to align:</label>
<select onchange="self.align">
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
<Timeline :data="self.data" :ref="self.ref" />
</div>`
}
import React, { useRef } from 'react';
import Timeline from '@lemonadejs/timeline/dist/react';
export default function App() {
const myRef = useRef();
const data = [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
];
return (<>
<label>Choose a position to align:</label>
<select onChange={(e) => myRef.current.align = e.target.value}>
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
<div style={{ height: '300px', width: '500px' }}>
<Timeline ref={myRef} data={data} />
</div>
</>);
}
<template>
<label>Choose a position to align:</label>
<select @change="this.$refs.timelineRef.current.align = $event.target.value">
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
<Timeline :data="data" ref="timelineRef" />
</template>
<script>
import Timeline from '@lemonadejs/timeline/dist/vue'
export default {
name: 'App',
components: {
Timeline
},
data() {
return {
data: [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
]
}
}
}
</script>
- See this React Timeline example on codesandbox;
- See this Vue Timeline example on codesandbox;
Monthly View Configuration
This setting enables a navigation control for monthly views, automatically grouping entries by their respective month and year.
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/style.min.css" />
<div id="root"></div>
<script>
const root = document.getElementById("root")
let data = [];
for (let i = 0; i < 500; i++) {
data.push({
date: faker.date.between(new Date(2023, 1, 1), new Date(2024, 12, 30)),
title: faker.commerce.productName(),
subtitle: faker.commerce.department(),
description: faker.commerce.productName(),
})
}
console.log(data)
const timeline = Timeline(root, {
data: data,
type: 'monthly',
align: 'left',
width: 500,
height: 500,
})
</script>
</html>
import lemonade from 'lemonadejs'
import Timeline from '@lemonadejs/timeline';
import { faker } from '@faker-js/faker';
import '@lemonadejs/timeline/dist/style.css';
export default function App() {
const self = this;
self.data = [];
for (let i = 0; i < 10; i++) {
self.data.push({
date: faker.date.between(new Date(2023, 1, 1), new Date(2024, 12, 30)),
title: faker.commerce.productName(),
subtitle: faker.commerce.department(),
description: faker.commerce.productName(),
})
}
return `<Timeline :data="self.data" :type="monthly" :width="500" :height="300" />`
}
import React, { useRef } from 'react';
import Timeline from '@lemonadejs/timeline/dist/react';
import { faker } from '@faker-js/faker';
import '@lemonadejs/timeline/dist/style.css';
let data = [];
for (let i = 0; i < 10; i++) {
data.push({
date: faker.date.between(new Date(2023, 1, 1), new Date(2024, 12, 30)),
title: faker.commerce.productName(),
subtitle: faker.commerce.department(),
description: faker.commerce.productName(),
})
}
export default function App() {
const myRef = useRef();
return (<Timeline ref={myRef} data={data} type="monthly" />);
}
<template>
<Timeline :data="data" type="monthly" ref="timelineRef" />
</template>
<script>
import Timeline from '@lemonadejs/timeline/dist/vue'
import { faker } from '@faker-js/faker';
export default {
name: 'App',
components: {
Timeline
},
data() {
let data = [];
for (let i = 0; i < 1000; i++) {
data.push({
date: faker.date.between(new Date(2023, 1, 1), new Date(2024, 12, 30)),
title: faker.commerce.productName(),
subtitle: faker.commerce.department(),
description: faker.commerce.productName(),
})
}
return {
data: data
}
}
}
</script>
Sorting
Configure the timeline to display events in ascending or descending chronological order.
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/timeline/dist/style.min.css" />
<label for="dropdown">Choose a sorting order:</label>
<select id="dropdown-order">
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
<div id="root"></div>
<script>
const root = document.getElementById("root")
const dropdown = document.getElementById("dropdown-order")
const tml = Timeline(root, {
data: [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
],
})
dropdown.addEventListener('change', (e) => {
tml.order = e.target.value;
})
</script>
</html>
import lemonade from 'lemonadejs'
import Timeline from '@lemonadejs/timeline';
import '@lemonadejs/timeline/dist/style.css';
export default function App() {
const self = this;
self.data = [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
]
self.sort = function() {
self.ref.order = e.target.value
}
return `<div>
<label>Choose a sorting order:</label>
<select onchange="self.sort">
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
<Timeline :data="self.data" :ref="self.ref" />
</div>`
}
import React, { useRef } from 'react';
import Timeline from '@lemonadejs/timeline/dist/react';
export default function App() {
const myRef = useRef();
const data = [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
];
return (<>
<label for="dropdown">Choose a sorting order:</label>
<select id="dropdown" onChange={(e) => myRef.current.order = e.target.value}>
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
<div style={{ height: '300px', width: '500px' }}>
<Timeline ref={myRef} data={data} />
</div>
</>);
}
<template>
<label for="dropdown">Choose a sorting order:</label>
<select id="dropdown" @change="this.$refs.timelineRef.current.order = $event.target.value">
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
<div style="height: 300px; width: 500px">
<Timeline :data="data" ref="timelineRef" />
</div>
</template>
<script>
import Timeline from '@lemonadejs/timeline/dist/vue'
export default {
name: 'App',
components: {
Timeline
},
data() {
return {
data: [
{ title: "Issue Identification", date: new Date(2022, 6, 1) },
{ title: "Root Cause Analysis", date: new Date(2022, 6, 2) },
{ title: "Implementation of Solution", date: new Date(2022, 6, 3) },
]
}
}
}
</script>