Timeline
날짜, 제목, 아이콘 또는 아바타가 포함된 이벤트 시퀀스를 표시하는 구성 요소입니다.
Usage
타임라인 구성 요소를 사용하여 타임라인의 항목 목록을 표시할 수 있습니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline :items="items" />
</template>Items 항목
items prop을 다음 속성을 가진 오브젝트 배열로 사용합니다.
date?: stringtitle?: string(-title?: string)description?: AvatarPropsicon?: stringavatar?: AvatarPropsvalue?: string | numberslot?: stringclass?: anyui?: { item?: ClassNameValue, container?: ClassNameValue, indicator?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, date?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline :default-value="2" :items="items" class="w-96" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline :default-value="2" :items="items" class="w-96" />
</template>Color 색상
color 소품을 사용하여 타임라인에서 활성 항목의 색상을 변경합니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline color="neutral" :default-value="2" :items="items" class="w-96" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline color="neutral" :default-value="2" :items="items" class="w-96" />
</template>Size
size prop을 사용하여 타임라인의 크기를 변경합니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline size="xs" :default-value="2" :items="items" class="w-96" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline size="xs" :default-value="2" :items="items" class="w-96" />
</template>방향
orientation 소품을 사용하여 타임라인의 방향을 변경합니다. 기본값은 vertical입니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment.
Mar 22 2025
Design Phase
User research and design workshops.
Mar 29 2025
Development Sprint
Frontend and backend development.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline orientation="horizontal" :default-value="2" :items="items" class="w-full" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline orientation="horizontal" :default-value="2" :items="items" class="w-full" />
</template>반전
반전 소품을 사용하여 타임라인의 방향을 반대로 합니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment.
Mar 22 2025
Design Phase
User research and design workshops.
Mar 29 2025
Development Sprint
Frontend and backend development.
Apr 5 2025
Testing & Deployment
QA testing and performance optimization.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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>
<UTimeline reverse v-model="value" orientation="vertical" :items="items" class="w-full" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/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>
<UTimeline reverse v-model="value" orientation="vertical" :items="items" class="w-full" />
</template>examples 예제
Control 활성화된 항목
default-value prop 또는 v-model 지시어를 사용하여 활성 항목을 제어할 수 있습니다. value가 제공되지 않으면 기본적으로 인덱스로 설정됩니다.
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22, 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29, 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5, 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: 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',
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>
<UTimeline v-model="active" :items="items" class="w-96" />
</template><script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { TimelineItem } from '@nuxt/ui'
const items: 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',
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>
<UTimeline v-model="active" :items="items" class="w-96" />
</template>value-key Prop을 사용하여 v-model 또는 default-value가 제공될 때 항목을 일치시키는 키를 변경합니다.Select 이벤트 포함
@select 리스너를 추가하여 항목을 클릭할 수 있도록 할 수 있습니다.
핸들러 함수는
Event 및 TimelineItem를 첫 번째 및 두 번째 인수로 수신합니다.Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22, 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29, 2025
Development Sprint
Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5, 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: 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',
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<string | number>('kickoff')
function onSelect(_e: Event, item: TimelineItem) {
if (item.value) {
active.value = item.value
}
}
</script>
<template>
<UTimeline v-model="active" :items="items" class="w-96" @select="onSelect" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { TimelineItem } from '@nuxt/ui'
const items: 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',
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<string | number>('kickoff')
function onSelect(_e: Event, item: TimelineItem) {
if (item.value) {
active.value = item.value
}
}
</script>
<template>
<UTimeline v-model="active" :items="items" class="w-96" @select="onSelect" />
</template>대체 레이아웃 포함
ui prop을 사용하여 대체 레이아웃이 있는 타임라인을 만듭니다.
Mar 15, 2025
Project Kickoff
Mar 22, 2025
Design Phase
Mar 29, 2025
Development Sprint
Apr 5, 2025
Testing & Deployment
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: TimelineItem[] = [
{
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>
<UTimeline
:items="items"
:default-value="2"
:ui="{
item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] rtl:even:translate-x-[calc(100%-2rem)] even:text-end'
}"
class="translate-x-[calc(50%-1rem)] rtl:-translate-x-[calc(50%-1rem)]"
/>
</template>사용자 지정 슬롯 포함
slot 속성을 사용하여 특정 항목을 사용자 정의합니다.
다음과 같은 슬롯에 액세스할 수 있습니다.
#{{ item.slot }}-indicator#{{ item.slot }}-date의 발음을 - {lang="ts-type"}#{{ item.slot }}-title#{{ item.slot }}-description
Mar 15, 2025
Project Kickoff
Kicked off the project with team alignment. Set up project milestones and allocated resources.
Mar 22, 2025
Design Phase
User research and design workshops. Created wireframes and prototypes for user testing.
Mar 29, 2025
Development Sprint

Frontend and backend development. Implemented core features and integrated with APIs.
Apr 5, 2025
Testing & Deployment
QA testing and performance optimization. Deployed the application to production.
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/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',
loading: 'lazy' as const
},
{
src: 'https://github.com/benjamincanac.png',
loading: 'lazy' as const
}
]
},
{
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 TimelineItem[]
</script>
<template>
<UTimeline :items="items" :default-value="2" class="w-96">
<template #development-title="{ item }">
<div class="flex items-center gap-1">
<span>{{ item.title }}</span>
<UAvatarGroup size="2xs">
<UAvatar v-for="(developer, index) of item.developers" :key="index" v-bind="developer" />
</UAvatarGroup>
</div>
</template>
</UTimeline>
</template>With 슬롯
사용 가능한 슬롯을 사용하여 보다 복잡한 타임라인을 만듭니다.
last year
J-Michalek opened this
last year
J-Michalek marked this pull request as ready for review
last year
benjamincanac commented on this
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.
last year
J-Michalek commented on this
Looks great! Good job on cleaning it up.
last year
benjamincanac merged this
<script lang="ts" setup>
import type { TimelineItem } from '@nuxt/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',
loading: 'lazy' as const
}
},
{
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: 'benjamincanac',
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/benjamincanac.png',
loading: 'lazy' as const
}
},
{
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',
loading: 'lazy' as const
}
},
{
username: 'benjamincanac',
date: '2025-05-27T11:01:20Z',
action: 'merged this',
icon: 'i-lucide-git-merge'
}
] satisfies TimelineItem[]
</script>
<template>
<UTimeline
:items="items"
size="xs"
:ui="{
date: 'float-end ms-1',
description: 'px-3 py-2 ring ring-default mt-2 rounded-md text-default'
}"
class="w-96"
>
<template #title="{ item }">
<span>{{ item.username }}</span>
<span class="font-normal text-muted"> {{ item.action }}</span>
</template>
<template #date="{ item }">
{{ useTimeAgo(new Date(item.date)) }}
</template>
</UTimeline>
</template>API
Props 파일
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
items | T[] | |
size | 'md' | "3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" |
color | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
orientation | 'vertical' | "horizontal" | "vertical"The orientation of the Timeline. |
valueKey | 'value' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the value from the item. |
defaultValue | string | number | |
reverse | boolean | |
modelValue | string | number | |
ui | { root?: SlotClass; item?: SlotClass; container?: SlotClass; indicator?: SlotClass; separator?: SlotClass; wrapper?: SlotClass; date?: SlotClass; title?: SlotClass; description?: SlotClass; } |
슬롯
| Slot | Type |
|---|---|
indicator | { item: T; } |
wrapper | { item: T; } |
date | { item: T; } |
title | { item: T; } |
description | { item: T; } |
Emits 파일
| Event | Type |
|---|---|
select | [event: Event, item: T] |
update:modelValue | [value: string | number | undefined] |
Theme (## 테마)
app.config.ts
export default defineAppConfig({
ui: {
timeline: {
slots: {
root: 'flex gap-1.5',
item: 'group relative flex flex-1 gap-3',
container: 'relative flex items-center gap-1.5',
indicator: 'group-data-[state=completed]:text-inverted group-data-[state=active]:text-inverted text-muted',
separator: 'flex-1 rounded-full bg-elevated',
wrapper: 'w-full',
date: 'text-dimmed text-xs/5',
title: 'font-medium text-highlighted text-sm',
description: 'text-muted text-wrap text-sm'
},
variants: {
orientation: {
horizontal: {
root: 'flex-row w-full',
item: 'flex-col',
separator: 'h-0.5'
},
vertical: {
root: 'flex-col',
container: 'flex-col',
separator: 'w-0.5'
}
},
color: {
primary: {
indicator: 'group-data-[state=completed]:bg-primary group-data-[state=active]:bg-primary'
},
secondary: {
indicator: 'group-data-[state=completed]:bg-secondary group-data-[state=active]:bg-secondary'
},
success: {
indicator: 'group-data-[state=completed]:bg-success group-data-[state=active]:bg-success'
},
info: {
indicator: 'group-data-[state=completed]:bg-info group-data-[state=active]:bg-info'
},
warning: {
indicator: 'group-data-[state=completed]:bg-warning group-data-[state=active]:bg-warning'
},
error: {
indicator: 'group-data-[state=completed]:bg-error group-data-[state=active]:bg-error'
},
neutral: {
indicator: 'group-data-[state=completed]:bg-inverted group-data-[state=active]:bg-inverted'
}
},
size: {
'3xs': '',
'2xs': '',
xs: '',
sm: '',
md: '',
lg: '',
xl: '',
'2xl': '',
'3xl': ''
},
reverse: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
reverse: false,
class: {
separator: 'group-data-[state=completed]:bg-primary'
}
},
{
color: 'primary',
reverse: true,
class: {
separator: 'group-data-[state=active]:bg-primary group-data-[state=completed]:bg-primary'
}
},
{
color: 'neutral',
reverse: false,
class: {
separator: 'group-data-[state=completed]:bg-inverted'
}
},
{
color: 'neutral',
reverse: true,
class: {
separator: 'group-data-[state=active]:bg-inverted group-data-[state=completed]:bg-inverted'
}
},
{
orientation: 'horizontal',
size: '3xs',
class: {
wrapper: 'pe-4.5'
}
},
{
orientation: 'horizontal',
size: '2xs',
class: {
wrapper: 'pe-5'
}
},
{
orientation: 'horizontal',
size: 'xs',
class: {
wrapper: 'pe-5.5'
}
},
{
orientation: 'horizontal',
size: 'sm',
class: {
wrapper: 'pe-6'
}
},
{
orientation: 'horizontal',
size: 'md',
class: {
wrapper: 'pe-6.5'
}
},
{
orientation: 'horizontal',
size: 'lg',
class: {
wrapper: 'pe-7'
}
},
{
orientation: 'horizontal',
size: 'xl',
class: {
wrapper: 'pe-7.5'
}
},
{
orientation: 'horizontal',
size: '2xl',
class: {
wrapper: 'pe-8'
}
},
{
orientation: 'horizontal',
size: '3xl',
class: {
wrapper: 'pe-8.5'
}
},
{
orientation: 'vertical',
size: '3xs',
class: {
wrapper: '-mt-0.5 pb-4.5'
}
},
{
orientation: 'vertical',
size: '2xs',
class: {
wrapper: 'pb-5'
}
},
{
orientation: 'vertical',
size: 'xs',
class: {
wrapper: 'mt-0.5 pb-5.5'
}
},
{
orientation: 'vertical',
size: 'sm',
class: {
wrapper: 'mt-1 pb-6'
}
},
{
orientation: 'vertical',
size: 'md',
class: {
wrapper: 'mt-1.5 pb-6.5'
}
},
{
orientation: 'vertical',
size: 'lg',
class: {
wrapper: 'mt-2 pb-7'
}
},
{
orientation: 'vertical',
size: 'xl',
class: {
wrapper: 'mt-2.5 pb-7.5'
}
},
{
orientation: 'vertical',
size: '2xl',
class: {
wrapper: 'mt-3 pb-8'
}
},
{
orientation: 'vertical',
size: '3xl',
class: {
wrapper: 'mt-3.5 pb-8.5'
}
}
],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
timeline: {
slots: {
root: 'flex gap-1.5',
item: 'group relative flex flex-1 gap-3',
container: 'relative flex items-center gap-1.5',
indicator: 'group-data-[state=completed]:text-inverted group-data-[state=active]:text-inverted text-muted',
separator: 'flex-1 rounded-full bg-elevated',
wrapper: 'w-full',
date: 'text-dimmed text-xs/5',
title: 'font-medium text-highlighted text-sm',
description: 'text-muted text-wrap text-sm'
},
variants: {
orientation: {
horizontal: {
root: 'flex-row w-full',
item: 'flex-col',
separator: 'h-0.5'
},
vertical: {
root: 'flex-col',
container: 'flex-col',
separator: 'w-0.5'
}
},
color: {
primary: {
indicator: 'group-data-[state=completed]:bg-primary group-data-[state=active]:bg-primary'
},
secondary: {
indicator: 'group-data-[state=completed]:bg-secondary group-data-[state=active]:bg-secondary'
},
success: {
indicator: 'group-data-[state=completed]:bg-success group-data-[state=active]:bg-success'
},
info: {
indicator: 'group-data-[state=completed]:bg-info group-data-[state=active]:bg-info'
},
warning: {
indicator: 'group-data-[state=completed]:bg-warning group-data-[state=active]:bg-warning'
},
error: {
indicator: 'group-data-[state=completed]:bg-error group-data-[state=active]:bg-error'
},
neutral: {
indicator: 'group-data-[state=completed]:bg-inverted group-data-[state=active]:bg-inverted'
}
},
size: {
'3xs': '',
'2xs': '',
xs: '',
sm: '',
md: '',
lg: '',
xl: '',
'2xl': '',
'3xl': ''
},
reverse: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
reverse: false,
class: {
separator: 'group-data-[state=completed]:bg-primary'
}
},
{
color: 'primary',
reverse: true,
class: {
separator: 'group-data-[state=active]:bg-primary group-data-[state=completed]:bg-primary'
}
},
{
color: 'neutral',
reverse: false,
class: {
separator: 'group-data-[state=completed]:bg-inverted'
}
},
{
color: 'neutral',
reverse: true,
class: {
separator: 'group-data-[state=active]:bg-inverted group-data-[state=completed]:bg-inverted'
}
},
{
orientation: 'horizontal',
size: '3xs',
class: {
wrapper: 'pe-4.5'
}
},
{
orientation: 'horizontal',
size: '2xs',
class: {
wrapper: 'pe-5'
}
},
{
orientation: 'horizontal',
size: 'xs',
class: {
wrapper: 'pe-5.5'
}
},
{
orientation: 'horizontal',
size: 'sm',
class: {
wrapper: 'pe-6'
}
},
{
orientation: 'horizontal',
size: 'md',
class: {
wrapper: 'pe-6.5'
}
},
{
orientation: 'horizontal',
size: 'lg',
class: {
wrapper: 'pe-7'
}
},
{
orientation: 'horizontal',
size: 'xl',
class: {
wrapper: 'pe-7.5'
}
},
{
orientation: 'horizontal',
size: '2xl',
class: {
wrapper: 'pe-8'
}
},
{
orientation: 'horizontal',
size: '3xl',
class: {
wrapper: 'pe-8.5'
}
},
{
orientation: 'vertical',
size: '3xs',
class: {
wrapper: '-mt-0.5 pb-4.5'
}
},
{
orientation: 'vertical',
size: '2xs',
class: {
wrapper: 'pb-5'
}
},
{
orientation: 'vertical',
size: 'xs',
class: {
wrapper: 'mt-0.5 pb-5.5'
}
},
{
orientation: 'vertical',
size: 'sm',
class: {
wrapper: 'mt-1 pb-6'
}
},
{
orientation: 'vertical',
size: 'md',
class: {
wrapper: 'mt-1.5 pb-6.5'
}
},
{
orientation: 'vertical',
size: 'lg',
class: {
wrapper: 'mt-2 pb-7'
}
},
{
orientation: 'vertical',
size: 'xl',
class: {
wrapper: 'mt-2.5 pb-7.5'
}
},
{
orientation: 'vertical',
size: '2xl',
class: {
wrapper: 'mt-3 pb-8'
}
},
{
orientation: 'vertical',
size: '3xl',
class: {
wrapper: 'mt-3.5 pb-8.5'
}
}
],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})
]
})변경 로그
No recent changes