Fliin
On this page

Blocks / commerce

Tracking steps

Shows where a delivery or a request stands as dated vertical steps, the current step written out in words and read with its rank by screen readers.

16 of 16 variants pass
Tracking steps, in-progress state
Platform
Brightness
Text scale
Direction

Import

Tracking steps is part of Fliin Pro. With a license key, sign in once with fliin login, then add it in a Flutter app where fliin init has run:

fliin login
fliin add tracking-steps

Also installs: core, chip, icons

Examples

In progress

A delivery under way: steps done, the current one, then those upcoming, each with its date.

Tracking steps, in-progress state
import 'package:your_app/ui/fliin/components/surface/fl_surface.dart';
import 'package:your_app/ui/fliin/components/tracking_steps/fl_tracking_steps.dart';
import 'package:flutter/widgets.dart';

class TrackingStepsInProgressExample extends StatelessWidget {
  const TrackingStepsInProgressExample({super.key});

  @override
  Widget build(BuildContext context) {
    return const FlSurface(
      child: FlTrackingSteps(
        currentLabel: 'Current',
        upcomingLabel: 'Upcoming',
        steps: [
          FlTrackingStep(title: 'Ordered', status: FlTrackingStepStatus.done, detail: 'October 22'),
          FlTrackingStep(title: 'Prepared', status: FlTrackingStepStatus.done, detail: 'October 23'),
          FlTrackingStep(title: 'Shipped', status: FlTrackingStepStatus.current, detail: 'October 24'),
          FlTrackingStep(title: 'Out for delivery', status: FlTrackingStepStatus.upcoming, detail: 'Expected on October 26'),
          FlTrackingStep(title: 'Delivered', status: FlTrackingStepStatus.upcoming, detail: 'Expected on October 27'),
        ],
      ),
    );
  }
}

Completed

Every step done: the journey reads as finished.

Tracking steps, completed state
import 'package:your_app/ui/fliin/components/surface/fl_surface.dart';
import 'package:your_app/ui/fliin/components/tracking_steps/fl_tracking_steps.dart';
import 'package:flutter/widgets.dart';

class TrackingStepsCompletedExample extends StatelessWidget {
  const TrackingStepsCompletedExample({super.key});

  @override
  Widget build(BuildContext context) {
    return const FlSurface(
      child: FlTrackingSteps(
        currentLabel: 'Current',
        upcomingLabel: 'Upcoming',
        steps: [
          FlTrackingStep(title: 'Ordered', status: FlTrackingStepStatus.done, detail: 'October 2'),
          FlTrackingStep(title: 'Shipped', status: FlTrackingStepStatus.done, detail: 'October 3'),
          FlTrackingStep(title: 'Delivered', status: FlTrackingStepStatus.done, detail: 'October 5'),
        ],
      ),
    );
  }
}

Started

Not only for parcels: any process in steps, here a support request just received. A step can do without its detail.

Tracking steps, started state
import 'package:your_app/ui/fliin/components/surface/fl_surface.dart';
import 'package:your_app/ui/fliin/components/tracking_steps/fl_tracking_steps.dart';
import 'package:flutter/widgets.dart';

class TrackingStepsStartedExample extends StatelessWidget {
  const TrackingStepsStartedExample({super.key});

  @override
  Widget build(BuildContext context) {
    return const FlSurface(
      child: FlTrackingSteps(
        currentLabel: 'Current',
        upcomingLabel: 'Upcoming',
        steps: [
          FlTrackingStep(title: 'Request received', status: FlTrackingStepStatus.current, detail: 'Today'),
          FlTrackingStep(title: 'Support reply', status: FlTrackingStepStatus.upcoming),
          FlTrackingStep(title: 'Resolved', status: FlTrackingStepStatus.upcoming),
        ],
      ),
    );
  }
}

Icons

Each step's own icon in its dot, in place of the check or the dot: the cart, the package on its way, the house.

Tracking steps, icons state
import 'package:your_app/ui/fliin/components/surface/fl_surface.dart';
import 'package:your_app/ui/fliin/components/tracking_steps/fl_tracking_steps.dart';
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/icons/fl_icons.dart';
import 'package:flutter/widgets.dart';

class TrackingStepsIconsExample extends StatelessWidget {
  const TrackingStepsIconsExample({super.key});

  @override
  Widget build(BuildContext context) {
    return FlSurface(
      child: FlTrackingSteps(
        currentLabel: 'Current',
        upcomingLabel: 'Upcoming',
        steps: [
          FlTrackingStep(
            title: 'Ordered',
            status: FlTrackingStepStatus.done,
            detail: 'October 22',
            icon: FlIcon(FlIcons.shoppingCart),
          ),
          FlTrackingStep(
            title: 'Shipped',
            status: FlTrackingStepStatus.current,
            detail: 'October 24',
            icon: FlIcon(FlIcons.paperPlane),
          ),
          FlTrackingStep(
            title: 'Delivered',
            status: FlTrackingStepStatus.upcoming,
            detail: 'Expected on October 27',
            icon: FlIcon(FlIcons.house),
          ),
        ],
      ),
    );
  }
}

Usage

The code the reference images render:

final example = ColoredBox(
  color: FlScope.of(context).colors.surface,
  child: SingleChildScrollView(
    padding: EdgeInsetsDirectional.all(FlScope.of(context).space.lg),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      spacing: FlScope.of(context).space.sm,
      children: [
        FlSurface(
          child: FlTrackingSteps(
            currentLabel: (variant.dir == TextDirection.rtl
                ? "الحالية"
                : "In progress"),
            upcomingLabel: (variant.dir == TextDirection.rtl
                ? "قادمة"
                : "Upcoming"),
            steps: [
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم الطلب"
                    : "Ordered"),
                status: FlTrackingStepStatus.done,
                detail: (variant.dir == TextDirection.rtl
                    ? "٢٢ أكتوبر"
                    : "October 22"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم التجهيز"
                    : "Prepared"),
                status: FlTrackingStepStatus.done,
                detail: (variant.dir == TextDirection.rtl
                    ? "٢٣ أكتوبر"
                    : "October 23"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم الشحن"
                    : "Shipped"),
                status: FlTrackingStepStatus.current,
                detail: (variant.dir == TextDirection.rtl
                    ? "٢٤ أكتوبر"
                    : "October 24"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "قيد التوصيل"
                    : "Out for delivery"),
                status: FlTrackingStepStatus.upcoming,
                detail: (variant.dir == TextDirection.rtl
                    ? "متوقع في ٢٦ أكتوبر"
                    : "Expected October 26"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم التوصيل"
                    : "Delivered"),
                status: FlTrackingStepStatus.upcoming,
                detail: (variant.dir == TextDirection.rtl
                    ? "متوقع في ٢٧ أكتوبر"
                    : "Expected October 27"),
              ),
            ],
          ),
        ),
        FlSurface(
          child: FlTrackingSteps(
            currentLabel: (variant.dir == TextDirection.rtl
                ? "الحالية"
                : "In progress"),
            upcomingLabel: (variant.dir == TextDirection.rtl
                ? "قادمة"
                : "Upcoming"),
            steps: [
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم الطلب"
                    : "Ordered"),
                status: FlTrackingStepStatus.done,
                detail: (variant.dir == TextDirection.rtl
                    ? "٢ أكتوبر"
                    : "October 2"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم الشحن"
                    : "Shipped"),
                status: FlTrackingStepStatus.done,
                detail: (variant.dir == TextDirection.rtl
                    ? "٣ أكتوبر"
                    : "October 3"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم التوصيل"
                    : "Delivered"),
                status: FlTrackingStepStatus.done,
                detail: (variant.dir == TextDirection.rtl
                    ? "٥ أكتوبر"
                    : "October 5"),
              ),
            ],
          ),
        ),
        FlSurface(
          child: FlTrackingSteps(
            currentLabel: (variant.dir == TextDirection.rtl
                ? "الحالية"
                : "In progress"),
            upcomingLabel: (variant.dir == TextDirection.rtl
                ? "قادمة"
                : "Upcoming"),
            steps: [
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم استلام الطلب"
                    : "Request received"),
                status: FlTrackingStepStatus.current,
                detail: (variant.dir == TextDirection.rtl ? "اليوم" : "Today"),
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "رد الدعم"
                    : "Support replied"),
                status: FlTrackingStepStatus.upcoming,
              ),
              FlTrackingStep(
                title: (variant.dir == TextDirection.rtl
                    ? "تم الحل"
                    : "Resolved"),
                status: FlTrackingStepStatus.upcoming,
              ),
            ],
          ),
        ),
      ],
    ),
  ),
);

API

FlTrackingStepStatus: enum {done, current, upcoming}
FlTrackingStepStatus.done: static final FlTrackingStepStatus
FlTrackingStepStatus.current: static final FlTrackingStepStatus
FlTrackingStepStatus.upcoming: static final FlTrackingStepStatus
FlTrackingStep: final class
FlTrackingStep.new: const new({required String title, required FlTrackingStepStatus status, String? detail, String? semanticLabel, Widget? icon})
FlTrackingStep.title: get String
FlTrackingStep.status: get FlTrackingStepStatus
FlTrackingStep.detail: get String?
FlTrackingStep.semanticLabel: get String?
FlTrackingStep.icon: get Widget?
FlTrackingSteps: class extends StatelessWidget
FlTrackingSteps.new: const new({super.key, required List<FlTrackingStep> steps, required String currentLabel, required String upcomingLabel, String? semanticLabel})
FlTrackingSteps.steps: get List<FlTrackingStep>
FlTrackingSteps.currentLabel: get String
FlTrackingSteps.upcomingLabel: get String
FlTrackingSteps.semanticLabel: get String?
FlTrackingSteps.build: Widget(BuildContext context)

Reference renders

The 16 images published with version 0.2.2, rendered by the shared harness on macOS with Flutter 3.47.7. fliin verify tracking-steps compares your copy to them.

iOS · Light
Tracking steps, iOS, Light, text 1.0×, Left to right
Text 1.0× · Left to right
Tracking steps, iOS, Light, text 1.0×, Right to left
Text 1.0× · Right to left
Tracking steps, iOS, Light, text 2.0×, Left to right
Text 2.0× · Left to right
Tracking steps, iOS, Light, text 2.0×, Right to left
Text 2.0× · Right to left
iOS · Dark
Tracking steps, iOS, Dark, text 1.0×, Left to right
Text 1.0× · Left to right
Tracking steps, iOS, Dark, text 1.0×, Right to left
Text 1.0× · Right to left
Tracking steps, iOS, Dark, text 2.0×, Left to right
Text 2.0× · Left to right
Tracking steps, iOS, Dark, text 2.0×, Right to left
Text 2.0× · Right to left
Android · Light
Tracking steps, Android, Light, text 1.0×, Left to right
Text 1.0× · Left to right
Tracking steps, Android, Light, text 1.0×, Right to left
Text 1.0× · Right to left
Tracking steps, Android, Light, text 2.0×, Left to right
Text 2.0× · Left to right
Tracking steps, Android, Light, text 2.0×, Right to left
Text 2.0× · Right to left
Android · Dark
Tracking steps, Android, Dark, text 1.0×, Left to right
Text 1.0× · Left to right
Tracking steps, Android, Dark, text 1.0×, Right to left
Text 1.0× · Right to left
Tracking steps, Android, Dark, text 2.0×, Left to right
Text 2.0× · Left to right
Tracking steps, Android, Dark, text 2.0×, Right to left
Text 2.0× · Right to left

Use it to

  • show the steps of a parcel delivery up to the doorstep
  • show the latest step reached and when
  • show when the steps still to come are expected
  • make each step readable with its rank by a screen reader
  • show a support request step by step
Not for
  • a bar that fills during a task: use a progress indicator (progress)
  • the dots of a carousel or an onboarding: use a page indicator (page-indicator)
States
  • In progress
  • Completed
  • Started

Arrows to move, Enter to open, Escape to close.