expressive_m3 library

Material 3 Expressive design tokens, motion and widgets for Flutter.

A drop-in expressive layer: emphasized easing + duration tokens, the M3 spring matrix as native SpringDescriptions, the full corner / spacing / elevation / type scales, the expressive polygon shapes, and a set of widgets (shape-morphing loading indicator, pull-to-refresh, wavy progress gauge, spring press response, shared-axis page transitions, spring page physics, fade-through tab switch).

Classes

CircularWavyProgress
A circular completion gauge with the count in the middle (e.g. 10/13) — an expressive progress motif. At rest it's a smooth ring; when progress increases it plays a one-shot wavy burst — the arc sweeps up from zero to the current value rippling, then the wave decays back to a smooth circle — so the motion rewards each step instead of rippling forever. Under reduced-motion it's a plain ring arc with no burst.
EmphasizedTextTheme
The Material 3 emphasized type scale (md.sys.typescale.emphasized.*).
ExpressiveButtonGroup
Material 3 Expressive button group — a connected row (or column) of buttons that share one continuous shape: the outer corners are fully rounded while the inner corners between segments are squared, so the group reads as a single control. Each segment springs on press via PressableScale.
ExpressiveElevation
Material 3 elevation — expressed as tone, not shadow.
ExpressiveFabMenu
Material 3 Expressive FAB menu — a floating action button that expands into a column of labelled mini-actions over a scrim, then collapses back.
ExpressiveFabMenuItem
One action in an ExpressiveFabMenu.
ExpressiveHaptics
A centralised, deliberately subtle haptic vocabulary. Routing every buzz through here keeps the feedback consistent and tunable in one place.
ExpressiveLoader
A single loading indicator for every loading state — page loading: branches, in-button spinners, dense rows — so the look stays uniform.
ExpressiveLoadingIndicator
Material 3 Expressive loading indicator — a shape-morphing spinner for indeterminate waits (the M3E replacement for a plain circular spinner). It morphs through the seven M3 indicator shapes while rotating, using the material_new_shapes morph engine via ShapeClip.
ExpressiveMotion
Centralised transition motion tokens (easing curves + durations) for Material 3 motion.
ExpressivePageTransitionsBuilder
A page transition using the Material 3 shared-axis (X) pattern, via the official animations package. The incoming route slides in along the horizontal axis and fades through while the outgoing route fades/slides out — the recognizable M3 forward/backward motion between hierarchy levels.
ExpressiveRadius
Corner-radius tokens — the full Material 3 (Expressive) corner scale.
ExpressiveRefreshIndicator
Pull-to-refresh that shows the M3-Expressive shape-morphing loading indicator instead of the stock circular RefreshProgressIndicator.
ExpressiveShapeBorder
An OutlinedBorder backed by an expressive polygon, so the M3E shapes can be used wherever a ShapeBorder is expected — Material(shape:), Card(shape:), button shape:, decoration: ShapeDecoration(shape:) — not only as a clip. material_new_shapes ships geometry → Path only and no ShapeBorder, so this wrapper bridges the gap (the third-party import stays inside this adapter).
ExpressiveShapeTokens
Semantic, role-keyed shape tokens built on ExpressiveRadius.
ExpressiveSpacing
Spacing scale — the 8dp Material 3 grid. Widgets read from here rather than inlining raw numeric literals.
ExpressiveSplitButton
Material 3 Expressive split button — a primary action joined to a small trailing segment that opens a menu. The two segments share one shape (the join is squared); the trailing chevron rotates while the menu is open.
ExpressiveSpringScheme
The Material 3 Expressive motion-physics scheme — the spring matrix M3 defines: two families × three speeds, as Flutter-native SpringDescriptions (driven via SpringDrive.springTo / AnimationController.animateWith — no third-party motion builder).
ExpressiveTextTheme
Material 3 baseline type scale (the md.sys.typescale.* tokens).
ExpressiveToolbar
Material 3 Expressive toolbar — a compact container of actions (usually IconButtons) in a floating pill or a docked bar, horizontal or vertical.
ExpressiveWavyCircularProgress
Material 3 Expressive wavy circular progress — a determinate ring whose active arc ripples. A leaner companion to a full progress gauge: no centre label, no burst, just a wavy determinate ring + remaining track.
ExpressiveWavyLinearProgress
Material 3 Expressive wavy linear progress — a horizontal bar whose active portion is a sine wave, with a small gap before the straight remaining track and a stop indicator at the far end.
MotionSchemeScope
Provides the active ExpressiveSpringScheme to a subtree — the framework-agnostic way to make the motion scheme swappable without pulling in a state-management dependency.
PressableScale
Wraps a tappable child with a Material 3 Expressive press response: the child springs down on pointer-down and bounces back on release using a real SpringSimulation (physics motion, not a fixed easing curve). The Listener is passive — it only observes pointer events, so the wrapped widget (button, card, …) keeps handling its own taps.
ShapeClip
Clips child to an expressive polygon, optionally morphing from from to shape by t (0..1) — e.g. a circle that morphs into a cookie on selection. The shape is fit (uniformly, centred) to the child's box, so a roughly-square box keeps the polygon undistorted.
SpringPagePhysics
Page-snapping scroll physics that settles on a spring instead of the stock friction curve — the feel a paged TabBarView gets when you fling between pages. Mirrors the framework's PageScrollPhysics page-rounding, but releases into a ScrollSpringSimulation built from the M3 ExpressiveSpringScheme expressive spatial-default spring (a partial-screen spatial motion — a touch of life that still settles cleanly).
TabSwitchTransition
A top-level destination switch — an M3 fade-through: when the active index changes, the incoming content fades in while scaling up a hair, with no lateral slide (M3 reserves shared-axis slides for forward/backward hierarchy, and fade-through for switching between unrelated top-level destinations).

Enums

ExpressiveShape
A handle on the Material 3 Expressive polygon shapes.
ExpressiveToolbarVariant
The two Material 3 Expressive toolbar treatments.

Extensions

EmphasizedTextThemeX on BuildContext
Ergonomic access to the emphasized scale: context.emphasizedText.titleLarge.
ExpressiveTextStyleX on TextStyle
Ergonomic typography transforms that map onto M3 guidance.
SpringDrive on AnimationController
Drive an AnimationController with a spring toward target, preserving the controller's current value and velocity so an interrupted animation retargets smoothly mid-flight — the reason M3 motion physics uses springs over fixed-duration curves. Use an unbounded controller (AnimationController.unbounded) for springs that overshoot.

Constants

expressivePageTransitionsTheme → const PageTransitionsTheme
Applies ExpressivePageTransitionsBuilder across every platform so route transitions look identical on Android, iOS and desktop.

Functions

fitExpressivePath(Path raw, Rect rect) Path
Scales raw uniformly (by its own bounds) to fill rect's shorter side and centres it within rect — robust regardless of the shape's native coords (some Material polygons exceed the 0..1 box).
insetAll(double value) EdgeInsetsDirectional
Directional-by-default padding (start/end swap in RTL). Prefer these over EdgeInsets.all/symmetric/only so leading/trailing lay out correctly in RTL — M3 spacing position semantics treat leading/trailing as directional.
insetOnly({double start = 0, double top = 0, double end = 0, double bottom = 0}) EdgeInsetsDirectional
insetSymmetric({double horizontal = 0, double vertical = 0}) EdgeInsetsDirectional
morphingButtonShape({required double restRadius, required double pressedRadius}) WidgetStateProperty<OutlinedBorder>
A button WidgetStateProperty shape that morphs its corner radius on press — the M3 Expressive shape-morph. At rest the shape uses restRadius; while pressed it snaps to pressedRadius and the host Material animates the transition. Pair with PressableScale for the combined squish + corner morph.