Skip to content
HyperUI for Flutter requires the Style package — this site itself ships no pub package.

Progress Bars

Ported from HyperUI’s Progress Bars — see Attribution.

class ProgressBars1Example extends StatelessWidget {
const ProgressBars1Example({super.key});
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
children: [
const Style('text-sm font-medium text-gray-900', child: Text('25%')),
Style(
'mt-2 h-2 w-full rounded-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 0.25,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full rounded-full bg-blue-600'),
),
),
],
);
}
}
class ProgressBars2Example extends StatelessWidget {
const ProgressBars2Example({super.key});
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md space-y-6 p-6',
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'flex justify-between gap-4',
children: [
Style(
'text-sm font-medium text-gray-900',
child: Text('Updating'),
),
Style(
'text-sm font-medium text-gray-900',
child: Text('25%'),
),
],
),
Style(
'mt-2 h-2 w-full rounded-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 0.25,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full rounded-full bg-blue-600'),
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'flex justify-between gap-4',
children: [
Style(
'text-sm font-medium text-gray-900',
child: Text('Downloading'),
),
Style(
'text-sm font-medium text-gray-900',
child: Text('100%'),
),
],
),
Style(
'mt-2 h-2 w-full rounded-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 1,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full rounded-full bg-green-600'),
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'flex justify-between gap-4',
children: [
Style(
'text-sm font-medium text-gray-900',
child: Text('Loading'),
),
Style(
'text-sm font-medium text-gray-900',
child: Text('50%'),
),
],
),
Style(
'mt-2 h-2 w-full rounded-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 0.5,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full rounded-full bg-gray-600'),
),
),
],
),
],
);
}
}
class ProgressBars3Example extends StatelessWidget {
const ProgressBars3Example({super.key});
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md space-y-6 p-6',
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'text-xs font-medium tracking-wide text-gray-700 uppercase',
child: Text('Download'),
),
Style(
'mt-2 h-1 w-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 0.25,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full bg-blue-600'),
),
),
const Style(
'mt-2 text-xs text-gray-700',
child: Text('1.2 of 3.8 MB'),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'text-xs font-medium tracking-wide text-gray-700 uppercase',
child: Text('File Conversion'),
),
Style(
'mt-2 h-1 w-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 0.75,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full bg-blue-600'),
),
),
const Style(
'mt-2 text-xs text-gray-700',
child: Text('3/4 files done'),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Style(
'text-xs font-medium tracking-wide text-gray-700 uppercase',
child: Text('File Sync'),
),
Style(
'mt-2 h-1 w-full bg-gray-200',
child: FractionallySizedBox(
widthFactor: 1,
alignment: AlignmentDirectional.centerStart,
child: Style('h-full bg-green-600'),
),
),
const Style(
'mt-2 text-xs text-gray-700',
child: Text('Completed'),
),
],
),
],
);
}
}
class CurrentColorIcon extends StatelessWidget
implements StyleReplacedElementWrapper {
const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override
Widget build(BuildContext context) {
final color = IconTheme.of(context).color ?? const Color(0xFF000000);
return SvgPicture.string(svg, theme: SvgTheme(currentColor: color));
}
}
class ProgressBars4Example extends StatelessWidget {
const ProgressBars4Example({super.key});
@override
Widget build(BuildContext context) {
return Style(
'mx-auto flex max-w-3xl flex-wrap gap-8 p-6',
children: [
Style(
'text-center',
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Style(
'relative mx-auto size-32',
children: [
Style(
'size-full',
child: Stack(
children: [
const Positioned.fill(
child: Style(
'text-gray-200',
child: CurrentColorIcon(_trackCircleSvg),
),
),
Positioned.fill(
child: Style(
'origin-center text-blue-600',
child: CurrentColorIcon(
_arcSvg(endX: 95, endY: 50, largeArcFlag: 0),
),
),
),
],
),
),
Style(
'absolute inset-0 grid place-content-center',
child: const Style(
'text-xl font-semibold text-gray-900',
child: Text('25%'),
),
),
],
),
const Style('mt-2 text-sm text-gray-700', child: Text('Loading')),
],
),
),
Style(
'text-center',
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Style(
'relative mx-auto size-32',
children: [
Style(
'size-full',
child: Stack(
children: [
const Positioned.fill(
child: Style(
'text-gray-200',
child: CurrentColorIcon(_trackCircleSvg),
),
),
Positioned.fill(
child: Style(
'origin-center text-green-600',
child: CurrentColorIcon(
_arcSvg(endX: 5, endY: 50, largeArcFlag: 1),
),
),
),
],
),
),
Style(
'absolute inset-0 grid place-content-center',
child: const Style(
'text-xl font-semibold text-gray-900',
child: Text('75%'),
),
),
],
),
const Style(
'mt-2 text-sm text-gray-700',
child: Text('Nearly done'),
),
],
),
),
],
);
}
}
const _trackCircleSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" aria-hidden="true"><circle cx="50" cy="50" r="45" fill="none" stroke="currentColor" stroke-width="8"/></svg>''';
String _arcSvg({
required double endX,
required double endY,
required int largeArcFlag,
}) =>
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" '
'aria-hidden="true"><path d="M50 5A45 45 0 $largeArcFlag 1 $endX $endY" '
'fill="none" stroke="currentColor" stroke-width="8" '
'stroke-linecap="round"/></svg>';