Use the Timeline component to display a list of items in a timeline.
<script setup lang="ts">
const items = ref([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline :items="items" />
</template>
Use the items prop as an array of objects with the following properties:
date?: stringtitle?: stringdescription?: AvatarPropsicon?: stringavatar?: AvatarPropsvalue?: string | numberslot?: stringclass?: anypohon?: { item?: ClassNameValue, container?: ClassNameValue, indicator?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, date?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }<script setup lang="ts">
import type { TimelineItem } from 'pohon-ui'
const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline :default-value="2" :items="items" class="w-96" />
</template>
Use the color prop to change the color of the active items in a Timeline.
<script setup lang="ts">
import type { TimelineItem } from 'pohon-ui'
const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline color="neutral" :default-value="2" :items="items" class="w-96" />
</template>
Use the size prop to change the size of the Timeline.
<script setup lang="ts">
import type { TimelineItem } from 'pohon-ui'
const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline size="xs" :default-value="2" :items="items" class="w-96" />
</template>
Use the orientation prop to change the orientation of the Timeline. Defaults to vertical.
<script setup lang="ts">
import type { TimelineItem } from 'pohon-ui'
const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline orientation="horizontal" :default-value="2" :items="items" class="w-full" />
</template>
Use the reverse prop to reverse the direction of the Timeline.
<script setup lang="ts">
import type { TimelineItem } from 'pohon-ui'
const items = ref<TimelineItem[]>([
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment.',
icon: 'i-lucide:rocket'
},
{
date: 'Mar 22 2025',
title: 'Design Phase',
description: 'User research and design workshops.',
icon: 'i-lucide:palette'
},
{
date: 'Mar 29 2025',
title: 'Development Sprint',
description: 'Frontend and backend development.',
icon: 'i-lucide:code'
},
{
date: 'Apr 5 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization.',
icon: 'i-lucide:check-circle'
}
])
</script>
<template>
<PTimeline reverse v-model="value" orientation="vertical" :items="items" class="w-full" />
</template>
You can control the active item by using the default-value prop or the v-model directive with the value of the item. If no value is provided, it defaults to the index as a string.
<script setup lang="ts">
import type { PTimelineItem } from 'pohon-ui'
import { onMounted, ref } from 'vue'
const items: Array<PTimelineItem> = [
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description:
'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket',
value: 'kickoff'
},
{
date: 'Mar 22, 2025',
title: 'Design Phase',
description:
'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette',
value: 'design'
},
{
date: 'Mar 29, 2025',
title: 'Development Sprint',
description:
'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code',
value: 'development'
},
{
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle',
value: 'deployment'
}
]
const active = ref(0)
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
setInterval(() => {
active.value = (active.value + 1) % items.length
}, 2000)
})
</script>
<template>
<PTimeline v-model="active" :items="items" class="w-96" />
</template>
Use the pohon prop to create a Timeline with alternating layout.
<script setup lang="ts">
import type { PTimelineItem } from 'pohon-ui'
const items: Array<PTimelineItem> = [
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
icon: 'i-lucide:rocket',
value: 'kickoff'
},
{
date: 'Mar 22, 2025',
title: 'Design Phase',
icon: 'i-lucide:palette',
value: 'design'
},
{
date: 'Mar 29, 2025',
title: 'Development Sprint',
icon: 'i-lucide:code',
value: 'development'
},
{
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
icon: 'i-lucide:check-circle',
value: 'deployment'
}
]
</script>
<template>
<PTimeline
:items="items"
:default-value="2"
:pohon="{ item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] even:text-right' }"
class="translate-x-[calc(50%-1rem)]"
/>
</template>
Use the slot property to customize a specific item.
You will have access to the following slots:
#{{ item.slot }}-indicator#{{ item.slot }}-date#{{ item.slot }}-title#{{ item.slot }}-description<script setup lang="ts">
import type { PTimelineItem } from 'pohon-ui'
const items = [
{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
subtitle: 'Project Initiation',
description:
'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide:rocket',
value: 'kickoff'
},
{
date: 'Mar 22, 2025',
title: 'Design Phase',
description:
'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide:palette',
value: 'design'
},
{
date: 'Mar 29, 2025',
title: 'Development Sprint',
description:
'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide:code',
value: 'development',
slot: 'development' as const,
developers: [
{
src: 'https://github.com/J-Michalek.png'
},
{
src: 'https://github.com/praburangki.png'
}
]
},
{
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide:check-circle',
value: 'deployment'
}
] satisfies Array<PTimelineItem>
</script>
<template>
<PTimeline :items="items" :default-value="2" class="w-96">
<template #development-title="{ item }">
<div class="flex gap-1 items-center">
<span>{{ item.title }}</span>
<PAvatarGroup size="2xs">
<PAvatar v-for="(developer, index) of item.developers" :key="index" v-bind="developer" />
</PAvatarGroup>
</div>
</template>
</PTimeline>
</template>
Use the available slots to create a more complex Timeline.
<script lang="ts" setup>
import type { PTimelineItem } from 'pohon-ui'
import { useTimeAgo } from '@vueuse/core'
const items = [
{
username: 'J-Michalek',
date: '2025-05-24T14:58:55Z',
action: 'opened this',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
},
{
username: 'J-Michalek',
date: '2025-05-26T19:30:14+02:00',
action: 'marked this pull request as ready for review',
icon: 'i-lucide:check-circle'
},
{
username: 'praburangki',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description:
"I've made a few changes, let me know what you think! Basically I updated the design, removed unnecessary divs, used Avatar component for the indicator since it supports icon already.",
avatar: {
src: 'https://github.com/praburangki.png'
}
},
{
username: 'J-Michalek',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description: 'Looks great! Good job on cleaning it up.',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
},
{
username: 'praburangki',
date: '2025-05-27T11:01:20Z',
action: 'merged this',
icon: 'i-lucide:git-merge'
}
] satisfies Array<PTimelineItem>
</script>
<template>
<PTimeline
:items="items"
size="xs"
:pohon="{
date: 'float-end ms-1',
description: 'px-3 py-2 ring ring-ring mt-2 rounded-md color-text'
}"
class="w-96"
>
<template #title="{ item }">
<span>{{ item.username }}</span>
<span class="color-text-muted font-normal"> {{ item.action }}</span>
</template>
<template #date="{ item }">
{{ useTimeAgo(new Date(item.date)) }}
</template>
</PTimeline>
</template>
| Prop | Default | Type |
|---|
| Slot | Type |
|---|
| Event | Type |
|---|
Below is the theme configuration skeleton for the PTimeline. Since the component is provided unstyled by default, you will need to fill in these values to apply your own custom look and feel. If you prefer to use our pre-built, opinionated styling, you can instead use our UnoCSS preset, this docs is using it as well.
export default defineAppConfig({
pohon: {
timeline: {
slots: {
root: '',
item: '',
container: '',
indicator: '',
separator: '',
wrapper: '',
date: '',
title: '',
description: ''
},
variants: {
orientation: {
horizontal: {
root: '',
item: '',
separator: ''
},
vertical: {
root: '',
container: '',
separator: ''
}
},
color: {
primary: {
indicator: ''
},
secondary: {
indicator: ''
},
success: {
indicator: ''
},
info: {
indicator: ''
},
warning: {
indicator: ''
},
error: {
indicator: ''
},
neutral: {
indicator: ''
}
},
size: {
'3xs': '',
'2xs': '',
xs: '',
sm: '',
md: '',
lg: '',
xl: '',
'2xl': '',
'3xl': ''
},
reverse: {
true: ''
}
},
compoundVariants: [],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
};
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import pohon from 'pohon-ui/vite'
export default defineAppConfig({
pohon: {
timeline: {
slots: {
root: '',
item: '',
container: '',
indicator: '',
separator: '',
wrapper: '',
date: '',
title: '',
description: ''
},
variants: {
orientation: {
horizontal: {
root: '',
item: '',
separator: ''
},
vertical: {
root: '',
container: '',
separator: ''
}
},
color: {
primary: {
indicator: ''
},
secondary: {
indicator: ''
},
success: {
indicator: ''
},
info: {
indicator: ''
},
warning: {
indicator: ''
},
error: {
indicator: ''
},
neutral: {
indicator: ''
}
},
size: {
'3xs': '',
'2xs': '',
xs: '',
sm: '',
md: '',
lg: '',
xl: '',
'2xl': '',
'3xl': ''
},
reverse: {
true: ''
}
},
compoundVariants: [],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
};