Lzh on GitHub

Timeline

一个显示带有日期、标题、图标或头像的事件序列的组件。

用法

Items

使用 items prop 作为对象数组,对象包含以下属性:

  • date?: string
  • title?: string
  • description?: AvatarProps
  • icon?: string
  • avatar?: AvatarProps
  • value?: string | number
  • slot?: string
  • class?: any
  • ui?: { item?: ClassNameValue, container?: ClassNameValue, indicator?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, separator?: 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>

颜色 (Color)

使用 color 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 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>

方向 (Orientation)

使用 orientation prop 更改时间线的方向。默认为 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>

反向

使用 reverse 属性可以反转时间轴的方向。

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 orientation="vertical" v-model="value" :items="items" class="w-full" />
</template>

示例

控制活动项目

你可以通过使用 default-value prop 或 v-model 指令以及项目的索引来控制活动项目。

<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 09.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 09.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,你也可以传递其中一个项目的 value

带交替布局

使用 ui prop 创建具有交替布局的时间线。

<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"
    :ui="{ item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] even:text-right' }"
    :default-value="2"
    class="translate-x-[calc(50%-1rem)]"
  />
</template>

带自定义插槽

使用 slot 属性自定义特定项目。

你将可以使用以下插槽:

  • #{{ item.slot }}-indicator
  • #{{ item.slot }}-date
  • #{{ item.slot }}-title
  • #{{ item.slot }}-description
<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 09.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/benjamincanac.png'
      }
    ]
  },
  {
    date: 'Apr 5, 2025',
    title: 'Testing & Deployment',
    description:
      'QA 09.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>

带插槽

使用可用插槽创建更复杂的时间线。

<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'
    }
  },
  {
    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'
    }
  },
  {
    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: 'benjamincanac',
    date: '2025-05-27T11:01:20Z',
    action: 'merged this',
    icon: 'i-lucide-git-merge'
  }
] satisfies TimelineItem[]
</script>

<template>
  <UTimeline
    :items="items"
    size="xs"
    class="w-96"
    :ui="{
      date: 'float-end ms-1',
      description: 'px-3 py-2 ring ring-default mt-2 rounded-md text-default'
    }"
  >
    <template #title="{ item }">
      <span>{{ item.username }}</span>
      <span class="font-normal text-muted">&nbsp;{{ item.action }}</span>
    </template>

    <template #date="{ item }">
      {{ useTimeAgo(new Date(item.date)) }}
    </template>
  </UTimeline>
</template>

API

Props

Prop Default Type
as

'div'

any

The element or component this component should render as.

items

TimelineItem[]

size

'md'

"2xl" | "md" | "3xs" | "2xs" | "xs" | "sm" | "lg" | "xl" | "3xl"

color

'primary'

"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"

orientation

'vertical'

"horizontal" | "vertical"

The orientation of the Timeline.

defaultValue

string | number

reverse

boolean

modelValue

string | number

ui

{ root?: ClassNameValue; item?: ClassNameValue; container?: ClassNameValue; indicator?: ClassNameValue; separator?: ClassNameValue; wrapper?: ClassNameValue; date?: ClassNameValue; title?: ClassNameValue; description?: ClassNameValue; }

Slots

Slot Type
indicator

{ item: TimelineItem; }

date

{ item: TimelineItem; }

title

{ item: TimelineItem; }

description

{ item: TimelineItem; }

Emits

Event Type
update:modelValue

string | number

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'
          }
        }
      }
    })
  ]
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'

export default defineConfig({
  plugins: [
    vue(),
    uiPro({
      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'
          }
        }
      }
    })
  ]
})
为了可读性,compoundVariants 中的某些颜色被省略。请查看 GitHub 上的源代码。