JavaScript Timeline

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>

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>