Vitral 0.2
Data

Timeline

Events on an axis, down the page or across it, with content on one side, the other, or alternating.

Import

main.ts
import { Timeline } from '@vitral/vue';

Opposite content

  1. 15/10/2026 10:30
    Ordered
  2. 15/10/2026 14:00
    Processing
  3. 16/10/2026 16:15
    Shipped
  4. 18/10/2026 10:00
    Delivered
<script setup lang="ts">import { Timeline } from '@vitral/vue'; const events = [    { status: 'Ordered', date: '15/10/2026 10:30', icon: 'file' },    { status: 'Processing', date: '15/10/2026 14:00', icon: 'refresh' },    { status: 'Shipped', date: '16/10/2026 16:15', icon: 'upload' },    { status: 'Delivered', date: '18/10/2026 10:00', icon: 'check' }];</script> <template>    <Timeline :value="events" aria-label="Order history" style="width: 100%">        <template #opposite="{ item }">            <small style="color: var(--vt-text-muted-color)">{{ (item as { date: string }).date }}</small>        </template>        <template #content="{ item }">{{ (item as { status: string }).status }}</template>    </Timeline></template>

Alternate, with icons

  1. Ordered
    15/10/2026 10:30
  2. Processing
    15/10/2026 14:00
  3. Shipped
    16/10/2026 16:15
  4. Delivered
    18/10/2026 10:00
<script setup lang="ts">import { Icon, Timeline } from '@vitral/vue'; const events = [    { status: 'Ordered', date: '15/10/2026 10:30', icon: 'file' },    { status: 'Processing', date: '15/10/2026 14:00', icon: 'refresh' },    { status: 'Shipped', date: '16/10/2026 16:15', icon: 'upload' },    { status: 'Delivered', date: '18/10/2026 10:00', icon: 'check' }];</script> <template>    <Timeline :value="events" align="alternate" aria-label="Order history, alternating" style="width: 100%">        <template #marker="{ item }">            <span style="display: flex; width: 2rem; height: 2rem; align-items: center; justify-content: center; border-radius: 50%; color: var(--vt-primary-contrast-color); background: var(--vt-primary-color)">                <Icon :icon="(item as { icon: string }).icon" />            </span>        </template>        <template #content="{ item }">            <strong>{{ (item as { status: string }).status }}</strong>            <div style="font-size: 0.75rem; color: var(--vt-text-muted-color)">{{ (item as { date: string }).date }}</div>        </template>    </Timeline></template>

Horizontal

  1. Ordered
  2. Processing
  3. Shipped
  4. Delivered
<script setup lang="ts">import { Timeline } from '@vitral/vue'; const events = [    { status: 'Ordered', date: '15/10/2026 10:30', icon: 'file' },    { status: 'Processing', date: '15/10/2026 14:00', icon: 'refresh' },    { status: 'Shipped', date: '16/10/2026 16:15', icon: 'upload' },    { status: 'Delivered', date: '18/10/2026 10:00', icon: 'check' }];</script> <template>    <Timeline :value="events" layout="horizontal" align="top" aria-label="Order steps" style="width: 100%">        <template #content="{ item }">{{ (item as { status: string }).status }}</template>    </Timeline></template>

API

Read from packages/vue/src/components/Timeline/types.ts, so it says what the component actually accepts.

Props

NameTypeDescription
valueany[]The events, in order.
align'left' | 'right' | 'alternate' | 'top' | 'bottom'Which side the content is on: `left`, `right` or `alternate` vertically; `top`, `bottom` or `alternate` horizontally.
layout'vertical' | 'horizontal'Events down the page (the default) or across it.
dataKeystringA field that identifies an event.

Plus pt, dt and unstyled from BaseProps, see pass-through and unstyled mode.

Slots

NameSlot propsDescription
content(props: { item: unknown; index: number })An event's content.
opposite(props: { item: unknown; index: number })What sits across the axis from the content: a date, say.
marker(props: { item: unknown; index: number })Replaces the marker.
connector(props: { item: unknown; index: number })Replaces the line to the next event.