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.
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-stepsExamples
In progress
A delivery under way: steps done, the current one, then those upcoming, each with its date.
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.
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.
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.
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.
















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