| j / k | Scroll down / up |
| gg | Scroll to top |
| G | Scroll to bottom |
| ⌘K / / | Open search |
| ? | Show this help |
| Esc | Close search / help |
| n / N | Next / previous section |
| h | Go to landing |
| d | Go to docs |
| : | Command mode — type section name |
Press ? or Esc to close
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.
| Mode | Behavior |
|---|---|
blocking | Dim + block all input (e.g. submit in flight) |
transparent | Spinner, input still allowed |
subtle | Small inline indicator only |
final loading = sl<LoadingCubit>();
loading.show(mode: LoadingMode.blocking);
try {
await _store.saveProfile(form);
loading.hide();
} catch (_) {
loading.hide();
} LoadingOverlay is mounted in app.dart above the shell but below toasts, so a success toast can appear after the spinner hides.
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()),
],
);
},
) AppShimmer or PaginatedListView — not the global spinner.