Skip to content

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

dart
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

dart
enum TimelineMode { start, alternating }
ModeLayoutUse
startSingle column — spine on the left, content on the rightHistory, audit, version timelines
alternatingPing-pong — tasks anchor left/right, milestones span full widthWorkflow / approval timelines

ActivityItem (sealed)

Three variants — picked by domain meaning, rendered automatically.

TaskActivityItem

Human or approver action — submission, approval, rejection, revision. Positioned by anchor.

dart
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.

dart
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.

dart
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.

dart
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:

dart
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),
)
StyleWrapperTitle styleUse
inlinenonebodyMedium w600Default — content lives inside a parent timeline card
cardCardbodyMedium w600Standalone use as a tappable list item
compactnonelabelMedium w600Narrow 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.

dart
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:

TypeUse
TimelineMain widget; can render scrollable or embedded timelines
TimelineItem / TimelineHeader / TimelineCustomEntry variants for content rows, grouped headers, and arbitrary rows
SpinePositionstart, end, or center spine placement
TimelineOrderOldest-first or newest-first ordering
TimelineGroupingDate headers with custom text or widget builders
EntrySpan / ItemAnchorFull-row entries and start/end/center anchoring
DotIndicator / IconIndicator / CustomIndicatorBuilt-in indicator primitives
TimelineThemeDataSpine width/color, gap, indicator column width, and header padding
  • InputsRemarksText for comment bodies
  • ThemingsuccessOf, criticalOf, warningOf, neutralOf resolvers
  • Field FormattingFieldFormatter.instance for timestamps