Skip to main content

Module progress

Module progress 

Source
Expand description

The Material 3 Expressive progress indicators: linear and circular, each flat or wavy, each determinate or indeterminate — the reference’s four named constructors over two widgets.

Ported from material_3_expressive v1.0.8 (MIT, © 2026 Paa Developments), lib/components/progress_indicators/ (retrieved 2026-08-19). Upstream: https://github.com/paadevelopments/material_3_expressive

This module owns the View/Widget wiring, colour resolution, and every paint call; motion owns the five animation controllers and the curve tables that drive them, and linear/circular own the geometry those numbers feed.

§Constructors: the reference’s named-constructor split, kept

M3EProgressIndicator ships four Dart named constructors over one widget class (m3e_progress_indicators.dart:29-100). All four are sibling functions here, so the mapping stays one-to-one:

ReferenceHere
M3EProgressIndicator.linear(...)linear_progress (alias LinearProgress)
M3EProgressIndicator.linearWavy(...)linear_wavy_progress (alias LinearWavyProgress)
M3EProgressIndicator.circular(...)circular_progress (alias CircularProgress)
M3EProgressIndicator.circularWavy(...)circular_wavy_progress (alias CircularWavyProgress)

Every knob a constructor only accepts when it is meaningful — amplitude/ amplitudeForProgress/wavelength/waveSpeed/trackStrokeWidth/ gapSize on the wavy ones, stopSize on linearWavy — is a builder method here instead, documented as inert where it has no use (the same shape [crate::slider]’s port takes, for the same reason: a constructor-gated builder would need a view type per variant). LinearProgressView::wavy/CircularProgressView::wavy flip a flat view to its wavy sibling, so linear_progress(v).wavy() and linear_wavy_progress(v) are the same thing.

§Controlled, like every other value-carrying widget here

Both views carry the app’s ProgressValue every frame — Determinate(f) for a known 0.0..=1.0 fraction, Indeterminate for an unknown-duration loop — and neither ever writes its own value (docs/CODE_STANDARDS.md’s Interaction Semantics). There is no callback: a progress indicator has no user interaction to report.

§Indeterminate motion is the reference choreography, transcribed

Indeterminate progress is not a single sweeping segment. Upstream runs five independent animation controllers, and this port transcribes their durations, curves, and timing tables exactly (motion carries the per-constant citations):

  • Linear — one 1750 ms cycle drives four separately-delayed, separately-eased fractions (firstHead/firstTail/secondHead/ secondTail, all on Cubic(0.3, 0, 0.8, 0.15)), painting two traveling lines with track and gaps between and around them.
  • Circular — a 6000 ms global rotation (1080°) and a 4500 ms additional rotation (360°) sum into the arc’s start angle, while a 1300 ms controller ping-pongs the arc’s own sweep between 10% and 87% of the circle. The classic and wavy circular variants share all three.

Every controller advances from the frame clock during paint (docs/WIDGETS_CODE_STANDARDS.md), never from stacked implicit animations and never from a wall clock.

§Wavy variants

A wavy indicator replaces the flat active track with a sine path: linear oscillates the track’s centreline, circular oscillates the ring’s radius. Both take their amplitude as a factor in 0..=1 scaled by the family’s own peak offset (linear 3dp, circular 1.6dp), resolved in the reference’s precedence order — an app-supplied curve of progress, then an app-supplied constant, then the default ramp, which flattens the wave entirely below 0.1 and at/above 0.95 progress so it never fights the round caps.

The phase itself never gates on progress upstream (_needsWavePhase is _isWavy alone); the amplitude ramp is what stills the wave near either end. This port keeps that rule and adds one documented divergence: when the resolved amplitude is 0 the phase clock is not advanced and no frame is requested, since a flat line’s phase is unobservable and a perpetual repaint for no visible motion is exactly what the paced-frame convention exists to avoid.

Reduce-motion: every loop here is perpetual and decorative, so it asks for paced frames (TickClass::CosmeticLoop) and, under MotionScheme::reduce_motion, freezes wherever it sits and stops requesting frames — the crate convention, matching [crate::slider]/[crate::loading_indicator].

§Round caps are load-bearing

Every span here is a stroke, not a filled rect: the reference paints all of them with StrokeCap.round, and its gap arithmetic already budgets for the half-stroke each cap adds past its endpoint (_visualGap inflates the gap by a whole stroke; the wavy indeterminate arm insets by another half). PaintScene::stroke_line/stroke_path reach kurbo::Stroke::new, whose caps and joins are round by default — a backend that squared them would shorten every span by a half stroke and reopen the gaps this module deliberately closes.

Structs§

CircularProgressView
A circular progress indicator, classic or wavy. See the module docs.
CircularProgressWidget
The retained widget for a CircularProgressView. See the module docs.
LinearProgressView
A linear progress indicator, flat or wavy. See the module docs.
LinearProgressWidget
The retained widget for a LinearProgressView. See the module docs.

Enums§

ProgressSize
Track-thickness variant of a flat linear indicator (M3EProgressIndicatorSize). Inert on every other variant: the wavy linear indicator sizes from its own stroke/amplitude, and the circular ones from their diameter.
ProgressValue
A progress indicator’s controlled value (see the module docs).

Functions§

CircularProgress
PascalCase alias for circular_progress, matching the widget-fn vocabulary (Button/Image/…).
CircularWavyProgress
PascalCase alias for circular_wavy_progress.
LinearProgress
PascalCase alias for linear_progress, matching the widget-fn vocabulary (Button/Image/…).
LinearWavyProgress
PascalCase alias for linear_wavy_progress.
circular_progress
Create a classic circular progress indicator driven by value (M3EProgressIndicator.circular).
circular_wavy_progress
Create a wavy circular progress indicator driven by value (M3EProgressIndicator.circularWavy).
linear_progress
Create a flat linear progress indicator driven by value (M3EProgressIndicator.linear).
linear_wavy_progress
Create a wavy linear progress indicator driven by value (M3EProgressIndicator.linearWavy).

Type Aliases§

AmplitudeCurve
An app-supplied amplitude factor as a function of progress (M3EProgressIndicator.amplitudeForProgress). Rc, not Box, so a view can be cloned into its widget the same way crate::slider’s AmplitudeCurve is.