blob: b548c2eace5768f81863f0f61d108883b5edf1da [file]
import 'package:jaspr/dom.dart';
import 'package:jaspr/jaspr.dart';
import '../../../utils/styles.dart';
/// A fullscreen loading overlay with a spinner and configurable text.
///
/// Use this component to show a blocking loading state on top of a page.
/// The overlay is absolutely positioned and covers its parent container.
class LoadingOverlay extends StatelessComponent {
const LoadingOverlay({required this.text, super.key});
/// The message displayed below the spinner.
final String text;
@override
Component build(BuildContext context) {
return div(classes: 'loading-overlay', [
const div(classes: 'loading-overlay-spinner', []),
span(classes: 'loading-overlay-text', [.text(text)]),
]);
}
@css
static List<StyleRule> get styles => [
css.keyframes('loading-overlay-spin', {
'0%': const Styles(raw: {'transform': 'rotate(0deg)'}),
'100%': const Styles(raw: {'transform': 'rotate(360deg)'}),
}),
css('.loading-overlay').styles(
display: .flex,
position: const Position.absolute(top: Unit.zero, left: Unit.zero),
zIndex: const ZIndex(1000),
width: 100.percent,
height: 100.percent,
flexDirection: .column,
justifyContent: .center,
alignItems: .center,
gap: Gap.all(16.px),
raw: {
'background-color': 'color-mix(in srgb, var(--color-surface) 75%, transparent)',
'backdrop-filter': 'blur(4px)',
},
),
css('.loading-overlay-spinner').styles(
width: 32.px,
height: 32.px,
border: Border.all(color: colorBorder, width: 3.px),
radius: .circular(999.px),
raw: {
'border-top-color': 'transparent',
'animation': 'loading-overlay-spin 0.8s linear infinite',
},
),
css('.loading-overlay-text').styles(
color: colorOnSurfaceVariant,
fontSize: 14.px,
fontWeight: .w500,
),
];
}