Spinner
A turning ring that says something is working.
import 'package:flutter/widgets.dart';
import 'ui/badge.dart';
import 'ui/button.dart';
import 'ui/spinner.dart';
class SpinnerDemo extends StatelessWidget {
const SpinnerDemo({super.key});
@override
Widget build(BuildContext context) => const Wrap(
spacing: 16,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Spinner(),
Button(onPressed: null, leading: Spinner(), child: Text('Saving')),
Badge(variant: BadgeVariant.secondary, leading: Spinner(), child: Text('Syncing')),
],
);
}
Add it
In your Flutter project:
$
ashlar add spinner
It writes spinner.dart into lib/ui, keeping any you already have, and adds ashlar_icons to pubspec.yaml. It needs ashlar_icons, which come with it.
Examples
Other ways to use it, each running live, with its code.
In a button
While it works.
// In a button: While it works.
import 'package:flutter/widgets.dart';
import 'ui/button.dart';
import 'ui/spinner.dart';
class SpinnerButtonExample extends StatelessWidget {
const SpinnerButtonExample({super.key});
@override
Widget build(BuildContext context) =>
const Button(onPressed: null, leading: Spinner(size: 16), child: Text('Saving…'));
}
API
Read from the source above: each parameter with its type, its default, and what it is for.
Spinnerclass
A turning ring that says something is working. Its colour and size come from the IconTheme, so inside a Button it matches the label.
| Parameter | Type | Default | What it is for |
|---|---|---|---|
size |
double? |
Its width and height; the icon size around it when not given. | |
color |
Color? |
Its colour; the icon colour around it when not given. | |
semanticLabel |
String |
'Loading' |
What a screen reader calls it when its visible text does not say, as for an icon alone. |
Source
What lands in your app. It is yours from then on: change it as you would your own code, and ashlar add
will not write over it.
lib/ui/spinner.dart 61 lines
// Ashlar UI: Spinner. Copied into your app by `ashlar add spinner`; it is yours to change.
import 'package:ashlar_icons/ashlar_icons.dart';
import 'package:flutter/widgets.dart';
/// A turning ring that says something is working. Its colour and size come from the
/// IconTheme, so inside a Button it matches the label.
///
/// ```dart
/// Button(onPressed: null, leading: Spinner(), child: Text('Saving'))
/// ```
class Spinner extends StatefulWidget {
const Spinner({
super.key,
this.size,
this.color,
this.semanticLabel = 'Loading',
});
/// Its width and height; the icon size around it when not given.
final double? size;
/// Its colour; the icon colour around it when not given.
final Color? color;
/// What a screen reader calls it when its visible text does not say, as for an icon
/// alone.
final String semanticLabel;
@override
State<Spinner> createState() => _SpinnerState();
}
class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin {
late final _turn = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
)..repeat();
@override
void dispose() {
_turn.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Semantics(
label: widget.semanticLabel,
liveRegion: true,
child: ExcludeSemantics(
child: RotationTransition(
turns: _turn,
child: AshlarIcon(
AshlarIconsRoundedStroke.loaderCircle,
size: widget.size,
color: widget.color,
),
),
),
);
}