smart_overlay 🌊
A premium, lightweight loading overlay manager for Flutter. Featuring the unique FluxWave (Wavy) Progress Indicator with full gradient support.
✨ Features
- 10 Unique Indicators:
FluxWave,Lumina,Hydra,Aura,Nova,Orbit,Eclipse,Nexus,Zenith, andVortex— no other loading package has this much visual variety in one place. - Full Animation Control: Every indicator supports
isAnimating(stop/resume from any condition — a switch, a timer, or a real async result) andspeed(how fast it loops), independent of each other. - Determinate or Indeterminate:
FluxWaveandHydraaccept a realvalue: 0.0–1.0for actual upload/download progress, not just endless spinning. - Two Overlay Styles:
SmartOverlay.show()for a full-screen block,SmartOverlay.showCustom()for a lightweight, non-blocking toast card. - Custom Indicators: Inject any custom widget as your progress indicator or toast icon.
- Built-in Accessibility: All loaders come with
Semanticssupport out of the box. - Gradients Galore: Apply beautiful gradients to your loaders for a high-end feel.
- Glassmorphism: Optional background blur (
useBlur) for the full-screen loader. - Respects Your App's Theme: No forced fonts — overlay text uses your app's existing
TextThemeautomatically. - Simple API: Easy-to-use
SmartOverlaystatic methods orBuildContextextensions. - Hybrid Messages: Use simple
Stringmessages or complexWidgetmessage builders.
🎬 Gallery
🚀 Quick Start
1. Installation
Add smart_overlay to your pubspec.yaml:
dependencies:
smart_overlay: ^0.1.0
2. Basic Usage
Show a simple full-screen loader using the named API (Professional) or extensions (Convenient):
// Named API
SmartOverlay.show(context: context, message: "Setting things up...");
// Access via context
context.showLoader(message: "Setting things up...");
// To hide
SmartOverlay.hide(); // Or context.hideOverlay();
3. Premium Gradient Style
Bring your UI to life with gradients and blur:
SmartOverlay.show(
context: context,
message: "Syncing your data...",
useBlur: true,
backgroundColor: Colors.indigo.withValues(alpha: 0.4),
gradient: LinearGradient(
colors: [Colors.purple, Colors.blueAccent],
),
);
4. Hybrid Messages (Advanced)
Inject complex widgets or rich text as your loading message:
SmartOverlay.show(
context: context,
messageWidget: Column(
children: [
Text("AI Syncing", style: TextStyle(fontWeight: FontWeight.bold)),
Text("Analyzing patterns...", style: TextStyle(fontSize: 12)),
],
),
);
5. Custom Indicator Style
Switch to the new professional fading dots or use your own widget:
context.showLoader(
message: "Premium experience...",
indicator: LuminaProgressIndicator(
size: 80,
color: Colors.white,
),
);
6. Direct Indicator Usage
All indicators can be used as standalone widgets anywhere in your UI:
// Standalone Lumina Dots
LuminaProgressIndicator(
size: 60,
gradient: SweepGradient(
colors: [Colors.blue, Colors.cyan],
),
)
7. Controlling Animation (Start / Stop / Speed / Progress)
Every indicator keeps animating indefinitely by default — that's not a bug, it's the point of a loading indicator. It stops only when you tell it to, via the isAnimating parameter. isAnimating is a plain bool, so it can be driven by absolutely anything: a switch, a timer, or a real condition in your app. speed and value are separate, independent controls — see the breakdown below.
a) Driven by a real async result (the common case)
bool _isSigningUp = false;
Future<void> _submit() async {
setState(() => _isSigningUp = true);
try {
await signUpApi(email, password);
} finally {
if (mounted) setState(() => _isSigningUp = false);
}
}
// in build():
_isSigningUp
? const FluxWaveProgressIndicator(size: 24)
: ElevatedButton(onPressed: _submit, child: const Text('Sign Up')),
Or, for a full-screen block, use SmartOverlay directly — it manages the same lifecycle for you, no state variable needed:
SmartOverlay.show(context: context, message: 'Creating your account...');
await signUpApi(email, password);
SmartOverlay.hide();
b) Driven by a fixed time, not a result
bool _isAnimating = true;
Timer(const Duration(seconds: 5), () {
setState(() => _isAnimating = false); // stops itself after 5 seconds
});
FluxWaveProgressIndicator(isAnimating: _isAnimating)
c) Driven by any condition — including combining several
FluxWaveProgressIndicator(
isAnimating: !(emailVerified && profileComplete && termsAccepted),
)
Whatever the expression is, the indicator reacts the moment it changes — there's no special "condition API" beyond passing a bool.
Speed controls how fast the loop runs — independent of whether it's running at all:
FluxWaveProgressIndicator(
isAnimating: _isUploading,
speed: const Duration(seconds: 2), // faster loop
)
8. Compact Toast Style
For a lighter-weight, non-blocking confirmation (e.g. "Saved!"), use showCustom instead of show. It renders a small card with an icon (or your own customWidget) beside a message, rather than a full-screen loader:
SmartOverlay.showCustom(
context: context,
message: 'Saved!',
customWidget: const Icon(Icons.check_circle, color: Colors.green),
boxColor: Colors.white,
textColor: Colors.black87,
autoDismissDuration: const Duration(seconds: 2),
);
// Or via the context extension:
context.showCustom(message: 'Saved!', customWidget: const Icon(Icons.check_circle));
🎛️ Indicator Parameters
Every indicator (FluxWave, Lumina, Hydra, Aura, Nova, Orbit, Eclipse, Nexus, Zenith, Vortex) shares this common set of parameters:
| Parameter | Description | Default |
|---|---|---|
size |
Width and height of the indicator's bounding box | Varies per indicator |
color |
Primary color. Defaults to the theme's primary color | null |
gradient |
Overrides color with a gradient fill/stroke |
null |
speed |
How long a single animation loop takes — controls how fast it looks, not whether it's running | Varies per indicator |
isAnimating |
Whether the loop is running at all. Set to false to freeze the indicator at its current frame instead of unmounting it |
true |
curve |
Easing curve applied to the animation | Curves.linear |
FluxWaveProgressIndicator and HydraProgressIndicator additionally accept:
| Parameter | Description |
|---|---|
value |
null (default) → indeterminate, loops forever. 0.0–1.0 → determinate: draws a fixed arc/fill for that exact fraction instead of looping. This does not animate on its own — update it yourself as your real progress changes (e.g. from an upload's byte-progress callback). speed still applies to the ring's background rotation even in determinate mode. |
Each indicator also has its own visual-specific parameters (waveCount, dotCount, rippleCount, etc.) — see each class's dartdoc for details, or the full reference below. A live, runnable example of all three isAnimating patterns above is in example/lib/widgets/animation_control_demo.dart.
🛠️ Configuration Options
SmartOverlay.show() — full-screen loader:
| Option | Description | Default |
|---|---|---|
backgroundColor |
Background scrim color behind the overlay | Colors.black.withAlpha(200) |
textColor |
Color of the message text | Colors.white |
useBlur |
Enable background glassmorphism blur | false |
gradient |
Apply a gradient to the progress indicator | null |
indicator |
Inject a custom indicator widget | FluxWaveProgressIndicator |
message |
Optional text to display below the loader | null |
messageWidget |
Inject a custom widget as the message | null |
autoDismissDuration |
If set, the overlay hides automatically | null (sticky) |
SmartOverlay.showCustom() — compact card toast (accepts message, messageWidget, indicator, backgroundColor, gradient, and autoDismissDuration above, plus):
| Option | Description | Default |
|---|---|---|
boxColor |
Background color of the card itself | Colors.white |
iconColor |
Color of the default indicator's icon/stroke | Colors.blue |
customWidget |
Replaces the leading icon/indicator entirely — e.g. a success checkmark | null |
textColor |
Color of the message text | Colors.black87 |
backgroundColor |
Background scrim behind the card | Colors.white.withAlpha(200) |
Opacity isn't a separate parameter —
backgroundColor,boxColor,textColor, andiconColorare all plainColor, and opacity is just the alpha channel of that color. UseColors.black.withValues(alpha: 0.6)for a darker, more solid scrim,Colors.indigo.withValues(alpha: 0.2)for a light tint, orColors.transparentfor none at all.
Both accept a full OverlayOptions object via the options: parameter as an escape hatch for anything not listed above.
📖 Complete Parameter Reference
Every parameter on every indicator, in one place — each block below uses all of that indicator's own fields.
FluxWave — synchronized scalloped wave path. Supports value for real progress.
FluxWaveProgressIndicator(
size: 64,
strokeWidth: 3,
waveCount: 10,
color: Colors.cyan,
backgroundColor: Colors.cyan.withValues(alpha: 0.15),
gradient: const LinearGradient(colors: [Colors.blue, Colors.cyan]),
speed: const Duration(seconds: 2),
isAnimating: true,
curve: Curves.easeInOut,
value: null, // or 0.0–1.0 for determinate progress
)
Lumina — dots fading and scaling in sequence around a ring.
LuminaProgressIndicator(
size: 60,
dotCount: 12,
dotSize: 5,
radius: 24,
color: Colors.deepPurple,
gradient: const SweepGradient(colors: [Colors.purple, Colors.pink]),
speed: const Duration(milliseconds: 1000),
isAnimating: true,
curve: Curves.linear,
)
Hydra — a liquid fill with an animated wavy surface. Supports value for real progress.
HydraProgressIndicator(
size: 70,
value: 0.6, // or null for indeterminate
waveAmplitude: 5,
waveFrequency: 2,
color: Colors.blue,
backgroundColor: Colors.blue.withValues(alpha: 0.1),
gradient: const LinearGradient(colors: [Colors.lightBlue, Colors.teal]),
speed: const Duration(seconds: 2),
isAnimating: true,
curve: Curves.linear,
)
Aura — pulsing concentric ripples from a center dot.
AuraProgressIndicator(
size: 65,
rippleCount: 4,
showCenter: true,
color: Colors.teal,
gradient: const LinearGradient(colors: [Colors.teal, Colors.cyan]),
speed: const Duration(milliseconds: 2400),
isAnimating: true,
curve: Curves.easeOut,
)
Nova — a pulsing center with expanding rings that briefly bloom into petals.
NovaProgressIndicator(
size: 65,
ringCount: 3,
strokeWidth: 2,
petalCount: 8, // 0 disables petals
color: Colors.deepOrange,
gradient: const LinearGradient(colors: [Colors.orange, Colors.red]),
speed: const Duration(milliseconds: 2400),
isAnimating: true,
curve: Curves.linear,
)
Orbit — dots orbiting a track with a comet trail, or optional sparkles.
OrbitProgressIndicator(
size: 65,
dotCount: 3,
dotSize: 5,
showSparkle: true,
sparkleCount: 12,
sparkleColor: Colors.amber,
color: Colors.indigo,
secondaryColor: Colors.indigo.withValues(alpha: 0.3),
gradient: const LinearGradient(colors: [Colors.indigo, Colors.blue]),
speed: const Duration(milliseconds: 1800),
isAnimating: true,
curve: Curves.fastOutSlowIn,
)
Eclipse — two circles growing and shrinking out of phase.
EclipseProgressIndicator(
size: 65,
color: Colors.pink,
secondaryColor: Colors.pink.withValues(alpha: 0.4),
gradient: const LinearGradient(colors: [Colors.purple, Colors.pink]),
speed: const Duration(seconds: 2),
isAnimating: true,
curve: Curves.easeInOut,
)
Nexus — radial tick marks whose opacity sweeps around, like a clock face.
NexusProgressIndicator(
size: 50,
barCount: 12,
strokeWidth: 3.5,
color: Colors.green,
gradient: const LinearGradient(colors: [Colors.green, Colors.teal]),
speed: const Duration(seconds: 1),
isAnimating: true,
curve: Curves.linear,
)
Zenith — flower-petal shapes fading in and out in sequence.
ZenithProgressIndicator(
size: 50,
leafCount: 12,
color: Colors.deepPurple,
gradient: const LinearGradient(colors: [Colors.purple, Colors.deepPurple]),
speed: const Duration(milliseconds: 1200),
isAnimating: true,
curve: Curves.linear,
)
Vortex — arrow-tipped arcs chasing each other around a track.
VortexProgressIndicator(
size: 50,
arrowCount: 3,
strokeWidth: 3.5,
color: Colors.blue,
gradient: const LinearGradient(colors: [Colors.blue, Colors.indigo]),
speed: const Duration(milliseconds: 1500),
isAnimating: true,
curve: Curves.linear,
)
📜 License
This project is licensed under the MIT License - see the LICENSE file for details.