Keyboard Shortcuts

j / kScroll down / up
ggScroll to top
GScroll to bottom
K / /Open search
?Show this help
EscClose search / help
n / NNext / previous section
hGo to landing
dGo to docs
:Command mode — type section name

Press ? or Esc to close

Systems

Loading States

A single LoadingCubit drives a global LoadingOverlay. Instead of scattering spinners, any async operation flips the global loading flag and the overlay appears on top of everything.

Three modes

ModeBehavior
blockingDim + block all input (e.g. submit in flight)
transparentSpinner, input still allowed
subtleSmall inline indicator only

Usage

lib/features/loading/logic/loading_cubit.dart
final loading = sl<LoadingCubit>();

loading.show(mode: LoadingMode.blocking);
try {
  await _store.saveProfile(form);
  loading.hide();
} catch (_) {
  loading.hide();
}

Overlay

LoadingOverlay is mounted in app.dart above the shell but below toasts, so a success toast can appear after the spinner hides.

lib/features/loading/presentation/widget/loading_overlay.dart
BlocBuilder<LoadingCubit, LoadingState>(
  builder: (context, state) {
    if (!state.isLoading) return const SizedBox.shrink();
    return Stack(
      children: [
        if (state.mode == LoadingMode.blocking) const ModalBarrier(dismissible: false),
        const Center(child: AppCircularIndicator()),
      ],
    );
  },
)
Convention: use the global overlay for app-level blocking work. For in-list loading, use AppShimmer or PaginatedListView — not the global spinner.
sam's arch — A Pragmatic Flutter Architecture