Timeline
ActivityTimeline is the CDX wrapper around the vyuh_timelines package. It maps a sealed ActivityItem hierarchy to internal timeline entries so callers think only in domain types — the spine, indicators, and layout are handled for you.
Import package:vyuh_cdx_ui/vyuh_cdx_ui.dart when you want ActivityTimeline. Import package:vyuh_timelines/vyuh_timelines.dart directly when you need the lower-level timeline primitive without CDX activity cards.
Quick example
ActivityTimeline(
mode: TimelineMode.alternating,
order: TimelineOrder.newestFirst,
showDateGroups: true,
items: [
MilestoneActivityItem(
title: 'Submitted for review',
milestoneType: MilestoneType.start,
timestamp: lot.submittedAt,
outcome: ActivityOutcome.primary,
formattedActorName: lot.submittedBy,
),
TaskActivityItem(
title: 'Approved',
anchor: ActivityAnchor.left,
outcome: ActivityOutcome.success,
timestamp: review.approvedAt,
senderName: review.approver,
comments: RemarksText(text: review.comment),
),
TaskActivityItem(
title: 'Revision requested',
anchor: ActivityAnchor.left,
outcome: ActivityOutcome.revision,
timestamp: review2.requestedAt,
senderName: review2.approver,
version: 2,
isPending: true,
),
MilestoneActivityItem(
title: 'Effective',
milestoneType: MilestoneType.terminal,
outcome: ActivityOutcome.success,
timestamp: lot.effectiveAt,
),
],
)TimelineMode
enum TimelineMode { start, alternating }| Mode | Layout | Use |
|---|---|---|
start | Single column — spine on the left, content on the right | History, audit, version timelines |
alternating | Ping-pong — tasks anchor left/right, milestones span full width | Workflow / approval timelines |
ActivityItem (sealed)
Three variants — picked by domain meaning, rendered automatically.
TaskActivityItem
Human or approver action — submission, approval, rejection, revision. Positioned by anchor.
TaskActivityItem(
title: 'Approved',
timestamp: review.approvedAt,
outcome: ActivityOutcome.success,
anchor: ActivityAnchor.left, // left / right / center
subtitle: 'After 1 round of revisions.',
senderName: review.approver,
senderWidget: EntityLink<User>(id: review.approverId), // optional — wins over senderName
formattedTimestamp: '2 hours ago',
comments: RemarksText(text: review.comment),
customContent: ApprovalDetails(review: review),
version: 2,
isPending: false,
)MilestoneActivityItem
System status marker — workflow start, intermediate checkpoint, terminal state. Centered on the spine in alternating mode; full-width band.
MilestoneActivityItem(
title: 'Effective',
milestoneType: MilestoneType.terminal, // start / checkpoint / terminal
outcome: ActivityOutcome.success,
timestamp: lot.effectiveAt,
subtitle: 'Released to production',
errorInfo: const MilestoneErrorInfo(
type: 'WorkflowError',
message: 'Approval expired',
isRetryable: true,
),
)When errorInfo is set, an info icon appears next to the milestone title — tapping it opens a diagnostics dialog with the type / message / retryable flag / optional details.
CustomActivityItem
Arbitrary content with a configurable indicator.
CustomActivityItem(
title: 'Version 2 published',
timestamp: version.publishedAt,
icon: FluentIcons.tag_24_regular,
iconColor: Colors.blue,
content: VersionCard(version: version),
)
// Or supply a custom indicator widget:
CustomActivityItem(
title: 'Custom row',
indicator: const _MyCustomIndicator(),
content: _MyContent(),
)Indicator resolution: indicator (full custom) > icon + iconColor (circle with icon) > default small primary dot.
ActivityOutcome
Drives icon + color through the CDX status palette.
enum ActivityOutcome {
success, // checkmark, success palette
failure, // dismiss, critical palette
revision, // edit, warning palette
warning, // warning triangle, warning palette
info, // info circle, info (= primary) palette
primary, // send icon, primary
neutral, // clipboard task, neutral palette
}ActivityEntryContent
A standalone content widget for use inside CustomActivityItem or any other timeline-like card. Provides title + actor + timestamp + optional content layout in three styles:
ActivityEntryContent(
title: 'Updated price',
subtitle: 'Was $99.99, now $89.99',
formattedTimestamp: 'Apr 18, 2026 14:30',
performerName: 'Jane Doe',
performerWidget: EntityLink<User>(id: 'user-123'),
style: ActivityEntryStyle.inline, // inline / card / compact
textAlign: TextAlign.start, // forces full-line alignment for right-anchored cards
onTap: () => navigator.openVersion(version),
)| Style | Wrapper | Title style | Use |
|---|---|---|---|
inline | none | bodyMedium w600 | Default — content lives inside a parent timeline card |
card | Card | bodyMedium w600 | Standalone use as a tappable list item |
compact | none | labelMedium w600 | Narrow surfaces — actor and timestamp inlined as actor · timestamp |
Date grouping
When showDateGroups: true (default), items are auto-grouped by date and labelled headers ("Today", "Yesterday", or dd MMM yyyy) are inserted between groups. Pass dateFormatter to customize the label.
Lower-level vyuh_timelines
Use the standalone package when the feed shape is not an activity log or when you want complete control over indicators and content layout.
import 'package:flutter/material.dart';
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:vyuh_timelines/vyuh_timelines.dart';
Timeline(
spinePosition: SpinePosition.start,
order: TimelineOrder.newestFirst,
grouping: const TimelineGrouping(),
entries: [
TimelineItem(
indicator: const IconIndicator(
FluentIcons.checkmark_circle_24_regular,
color: Colors.green,
),
content: const Text('Submitted for review'),
timestamp: submittedAt,
),
TimelineItem.full(
indicator: const DotIndicator(color: Colors.blue),
timestamp: effectiveAt,
),
],
)Public building blocks:
| Type | Use |
|---|---|
Timeline | Main widget; can render scrollable or embedded timelines |
TimelineItem / TimelineHeader / TimelineCustom | Entry variants for content rows, grouped headers, and arbitrary rows |
SpinePosition | start, end, or center spine placement |
TimelineOrder | Oldest-first or newest-first ordering |
TimelineGrouping | Date headers with custom text or widget builders |
EntrySpan / ItemAnchor | Full-row entries and start/end/center anchoring |
DotIndicator / IconIndicator / CustomIndicator | Built-in indicator primitives |
TimelineThemeData | Spine width/color, gap, indicator column width, and header padding |
Cross-links
- Inputs —
RemarksTextfor comment bodies - Theming —
successOf,criticalOf,warningOf,neutralOfresolvers - Field Formatting —
FieldFormatter.instancefor timestamps