Timeline ​
The Timeline component is used to display a chronological sequence of events or activities. It provides a visual representation of the order in which events occurred, allowing users to easily track and understand the progression of a process.
Basic usage ​
A basic timeline showing a sequence of events.
Quantity changed from 2032.00 to 2500.00.
NJNick JackQuantity changed from 1840.00 to 2000.00.
NJNick JackUnit of Measure changed from Gram to Unit
NJNick Jack
vue
<script setup lang="ts">
import { ref } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Timeline>
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<div class="tw-max-w-[246px]">
<h3 class="tw-mb-3 tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</div>
</TimelineItem>
</Timeline>
</template>
Side ​
The timeline component can receive a side
prop to display the content on the start | end side of the timeline.
Start side ​
Quantity changed from 2032.00 to 2500.00.
NJNick JackQuantity changed from 1840.00 to 2000.00.
NJNick JackUnit of Measure changed from Gram to Unit
NJNick Jack
vue
<script setup lang="ts">
import { ref } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Timeline side="start">
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<div class="tw-max-w-[246px]">
<h3 class="tw-mb-3 tw-text-right tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-justify-end tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-order-first tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</div>
</TimelineItem>
</Timeline>
</template>
Opposite content ​
The timeline component exposes the opposite slot to add content to the opposite side of the main content.
Quantity changed from 2032.00 to 2500.00.
NJNick JackeditedFeb 28, 20244:00 AMQuantity changed from 1840.00 to 2000.00.
NJNick JackeditedDec 19, 20233:06 AMUnit of Measure changed from Gram to Unit
NJNick JackeditedNov 14, 202311:50 AM
vue
<script setup lang="ts">
import { format } from 'date-fns';
import { ref } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Chip from '../../../src/components/Chip/Chip.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Timeline>
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<template #opposite>
<div class="tw-text-right">
<Chip class="tw-mb-[6px] tw-py-1.5 tw-font-bold">
{{ changeLogEvent.status.label }}
</Chip>
<div class="tw-text-xs tw-text-ice-700">
<span class="tw-block">{{ format(changeLogEvent.date, 'PP') }}</span>
<span class="tw-block">{{ format(changeLogEvent.date, 'p') }}</span>
</div>
</div>
</template>
<div class="tw-max-w-[246px]">
<h3 class="tw-mb-3 tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</div>
</TimelineItem>
</Timeline>
</template>
Content density ​
The Timeline component can receive a density
prop to set the spacing around the content.
Compact ​
Quantity changed from 2032.00 to 2500.00.
NJNick JackQuantity changed from 1840.00 to 2000.00.
NJNick JackUnit of Measure changed from Gram to Unit
NJNick Jack
vue
<script setup lang="ts">
import { ref } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Timeline density="compact">
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<h3 class="tw-mb-3 tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</TimelineItem>
</Timeline>
</template>
Comfortable ​
Quantity changed from 2032.00 to 2500.00.
NJNick JackQuantity changed from 1840.00 to 2000.00.
NJNick JackUnit of Measure changed from Gram to Unit
NJNick Jack
vue
<script setup lang="ts">
import { ref } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Timeline density="comfortable">
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<h3 class="tw-mb-3 tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</TimelineItem>
</Timeline>
</template>
Within a Drawer ​
An example using a timeline inside a drawer Modal.
vue
<script setup lang="ts">
import { format } from 'date-fns';
import { ref, useCssModule } from 'vue';
import Avatar from '../../../src/components/Avatar/Avatar.vue';
import Button from '../../../src/components/Button/Button.vue';
import Chip from '../../../src/components/Chip/Chip.vue';
import Modal from '../../../src/components/Modal/Modal.vue';
import Timeline from '../../../src/components/Timeline/Timeline.vue';
import TimelineItem from '../../../src/components/TimelineItem/TimelineItem.vue';
const classes = useCssModule();
const emit = defineEmits(['dismiss']);
export interface ChangeLogEvent {
date: Date;
title: string;
status: {
label: string;
colorScheme: string;
};
avatar: {
name: string;
};
}
const changeLogEvents = ref<ChangeLogEvent[]>([
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2024, 1, 29, 4, 14, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 47, 0),
title: 'Unit of Measure changed from Unit to Gram',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2024, 1, 29, 4, 14, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 47, 0),
title: 'Unit of Measure changed from Unit to Gram',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2024, 1, 28, 4, 0, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2024, 1, 29, 4, 14, 0),
title: 'Quantity changed from 2032.00 to 2500.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 11, 19, 3, 6, 0),
title: 'Quantity changed from 1840.00 to 2000.00.',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 50, 0),
title: 'Unit of Measure changed from Gram to Unit',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
{
date: new Date(2023, 10, 14, 11, 47, 0),
title: 'Unit of Measure changed from Unit to Gram',
status: {
label: 'edited',
colorScheme: 'blue',
},
avatar: {
name: 'Nick Jack',
},
},
]);
</script>
<template>
<Modal title="Product Change Log" position="right" size="narrow" @dismiss="emit('dismiss')">
<Timeline>
<TimelineItem v-for="(changeLogEvent, index) in changeLogEvents" :key="index">
<template #opposite>
<div class="tw-text-right">
<Chip class="tw-mb-[6px] tw-py-1.5 tw-font-bold">
{{ changeLogEvent.status.label }}
</Chip>
<div class="tw-text-xs tw-text-ice-700">
<span class="tw-block">{{ format(changeLogEvent.date, 'PP') }}</span>
<span class="tw-block">{{ format(changeLogEvent.date, 'p') }}</span>
</div>
</div>
</template>
<div class="tw-max-w-[246px]">
<h3 class="tw-mb-3 tw-text-base tw-text-ice-900">
{{ changeLogEvent.title }}
</h3>
<div class="tw-flex tw-items-center tw-gap-[6px]">
<Avatar :name="changeLogEvent.avatar.name" bg-color="purple-500" text-color="white" />
<span class="tw-text-sm tw-text-ice-700">{{ changeLogEvent.avatar.name }}</span>
</div>
</div>
</TimelineItem>
</Timeline>
<template #footer>
<Button :class="classes['change-log__button']" secondary class="tw-w-full" @click="emit('dismiss')">
Close
</Button>
</template>
</Modal>
</template>
<style module>
footer:has(.change-log__button) {
border-top: 1px solid theme('colors.ice.500');
}
</style>