CnTimelineStages
Visualizes sequential progression through named stages. Stages are automatically classified as completed (before current), current, or upcoming (after current). Supports horizontal and vertical orientations, small/medium sizes, clickable stages with keyboard navigation (roving tabindex), and ARIA roles.
Try it
Loading CnTimelineStages playground…
Usage
<!-- Basic horizontal timeline -->
<CnTimelineStages
:stages="[
{ id: 'new', label: 'New' },
{ id: 'review', label: 'In Review', subtitle: 'Since Mar 15' },
{ id: 'approved', label: 'Approved' },
{ id: 'done', label: 'Done' },
]"
current-stage="review" />
<!-- Vertical, clickable — for pipeline stage selection -->
<CnTimelineStages
:stages="pipelineStages"
:current-stage="deal.stage"
orientation="vertical"
:clickable="true"
@stage-click="onStageClick" />
<!-- Small size, custom indicator via slot -->
<CnTimelineStages :stages="stages" current-stage="active" size="small">
<template #indicator="{ stage, state }">
<span :class="['my-dot', `my-dot--${state}`]" />
</template>
</CnTimelineStages>
function onStageClick({ stage, index }) {
updateDealStage(stage.id)
}
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
stages | Array | ✓ | — | Stage objects: { id, label, subtitle? }. id must be unique; subtitle is optional secondary text |
currentStage | String | Number | null | id of the active stage. Stages before it are completed, stages after are upcoming. null = all upcoming | |
orientation | String | 'horizontal' | Layout direction: 'horizontal' or 'vertical' | |
size | String | 'medium' | Indicator size: 'medium' (32px) or 'small' (20px) | |
clickable | Boolean | false | Whether stages emit stage-click and support arrow-key navigation | |
ariaLabel | String | 'Progress stages' | Accessible label for the timeline container |
Events
| Event | Payload | Description |
|---|---|---|
stage-click | { stage, index } | Emitted when a clickable stage is activated via click, Enter, or Space |
Slots
| Slot | Scope | Description |
|---|---|---|
indicator | { stage, index, state } | Custom indicator element replacing the default checkmark/dot |
label | { stage, index, state } | Custom label block replacing the default label + subtitle |
Stage states
| State | Condition |
|---|---|
'completed' | Stage index < current stage index |
'current' | Stage matches currentStage |
'upcoming' | Stage index > current stage index |
Reference (auto-generated)
The tables below are generated from the SFC source via vue-docgen-cli. They reflect what's actually in CnTimelineStages.vue and update automatically whenever the component changes.
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
stages | { id: string, label: string, subtitle: string }[] | ✓ | — | Array of stage objects. Each must have id (unique) and label (display text). Optional subtitle for secondary text below the label. |
currentStage | union | null | The id of the currently active stage. Stages before it are "completed", stages after it are "upcoming". If null/undefined or not matching any id, all stages are "upcoming". | |
orientation | string | 'horizontal' | Layout orientation: "horizontal" (left-to-right) or "vertical" (top-to-bottom). | |
size | string | 'medium' | Size variant: "medium" (32px indicators) or "small" (20px indicators). | |
clickable | boolean | false | Whether stages are clickable. When true, stages emit stage-click on click/Enter/Space and support keyboard navigation with arrow keys. | |
ariaLabel | string | () => t('nextcloud-vue', 'Progress stages') | Accessible label for the timeline container. |
Events
| Name | Payload | Description |
|---|---|---|
stage-click | — | Emitted when a clickable stage is activated (click, Enter, or Space). |
Slots
| Name | Bindings | Description |
|---|---|---|
indicator | stage, index, state | |
label | stage, index, state |