Angular Loading Spinner & Overlay | ng-hub-ui-loading

Angular loading component with spinner, dots, bars, pulse and ring indicators in inline, overlay and fullscreen modes, plus a service for app-wide blocking overlays.

API reference

Here's the full contract for loading: everything you can bind, listen to, project and theme, gathered in one place. Wire up what you need and style what you want — it's standalone and signal-friendly.

Inputs

Dial loading in with 16 inputs. Bind them like any Angular @Input.

NameTypeDefaultDescription
hub-loading · mode'inline' | 'overlay' | 'fullscreen''inline'Where the block sits. `inline` takes part in normal document flow and reserves its own space; `overlay` is positioned absolutely and covers the nearest positioned ancestor; `fullscreen` is fixed to the viewport.
hub-loading · variant'spinner' | 'dots' | 'bars' | 'pulse' | 'ring''spinner'Which pure-CSS indicator to render. Ignored while `image` is set, since the image replaces the built-in indicator.
hub-loading · imagestring | nullnullURL or data URI rendered instead of the built-in indicator, typically a brand mark. Its box is sized by `--hub-loading-image-size`.
hub-loading · imageAnimation'none' | 'spin' | 'pulse''none'Motion applied to `image`, and inert while no image is set. `spin` suits a radially symmetric mark, `pulse` keeps a wordmark upright and legible, and `none` leaves it still.
hub-loading · messagestring | nullnullText rendered below the indicator, and what the live region announces when the block appears. `null` renders no message.
hub-loading · size'sm' | 'md' | 'lg''md'Size step feeding `--hub-loading-size`. The token stays overridable on its own when a layout needs a size the three steps do not cover.
hub-loading · colorstring | nullnullAccent for the indicator, normalised by `resolveHubAccent()` into the single `--hub-loading-accent` slot. A bare name such as `primary` resolves to a `--hub-sys-color-*` token and follows the theme; a hex, an `oklch()` literal or a `var(...)` reference is used verbatim. `null` leaves the token's own cascade default in place.
hub-loading · backdropbooleantruePaints the translucent scrim over the covered content. Ignored in `inline` mode, which covers nothing.
hub-loading · ariaLabelstring'Loading'Accessible name announced by the host's `role="status"` live region.
hub-loading-bar · mode'inline' | 'overlay' | 'fixed''inline'Where the strip sits. `inline` takes part in normal flow and reserves its own row, so nothing shifts when the bar appears; `overlay` is positioned absolutely against the nearest positioned ancestor — the navbar you gave `position: relative`; `fixed` pins it to the viewport at `--hub-loading-bar-offset`.
hub-loading-bar · placement'top' | 'bottom''top'Which edge the `overlay` and `fixed` modes attach to. `bottom` is what hangs the bar off the underside of a navbar; `inline` ignores it.
hub-loading-bar · progressnumber | null | undefinedundefinedTakes the bar over. Left unbound it follows `HubLoadingBarService`; a number from 0 to 100 drives it directly and is published as `aria-valuenow`; `null` hides it.
hub-loading-bar · indeterminatebooleanfalseSweeps a fragment back and forth instead of filling, for work with no measurable progress. The announced value is withheld, which is how ARIA marks a progressbar of unknown position.
hub-loading-bar · glowbooleantrueSoft glow trailing the leading edge — the detail that still reads as movement between trickle ticks.
hub-loading-bar · colorstring | nullnullAccent for the fill. A bare name resolves to a `--hub-sys-color-*` token and follows the theme; a hex, an `oklch()` or a `var(...)` is used verbatim.
hub-loading-bar · ariaLabelstring'Loading'Accessible name for the host’s `role="progressbar"`.

Outputs

No outputs documented yet.

Methods

Drive loading from code — 14 methods on its programmatic surface.

NameSignatureReturnsDescription
HubLoadingService.showshow(options?: HubLoadingOptions): voidvoidRegisters one caller and mounts the fullscreen overlay if it is not up yet. Only the keys actually supplied are applied over the application defaults, so nested calls compose instead of resetting each other.
HubLoadingService.hidehide(): voidvoidRetires one caller and tears the overlay down once none are left. The counter is clamped at zero, so a stray `hide()` cannot turn a later `show()` into a no-op.
HubLoadingService.hideAllhideAll(): voidvoidDrops every pending caller at once and removes the overlay immediately. An escape hatch for error handlers and route changes, not a substitute for balanced `show()` / `hide()` pairs.
HubLoadingService.updateupdate(options: HubLoadingOptions): voidvoidRe-dresses the live overlay — a progress message that changes mid-operation, a variant swap — without touching the reference counter.
HubLoadingService.isLoadingisLoading: Signal<boolean>Signal<boolean> — true while at least one reference is heldSignal that is true while at least one caller is still waiting. Safe to read during server-side rendering, where the counter runs but no overlay is mounted.
HubLoadingBarService.startstart(): voidvoidRegisters one caller. The first begins a cycle — after the grace period, not immediately — and the rest simply join the count.
HubLoadingBarService.completecomplete(): voidvoidRetires one caller. Once none are left the bar runs to 100% and fades away, or disappears unseen if the grace period swallowed the whole operation.
HubLoadingBarService.completeAllcompleteAll(): voidvoidDrops every pending caller and completes the bar at once. For an error handler, or a caller that never balanced its `start()`.
HubLoadingBarService.setset(value: number): voidvoidMoves the bar to an exact value and reveals it without waiting out the grace period. For work whose percentage is real; the value is clamped to 0–100 but not to the trickle ceiling.
HubLoadingBarService.incinc(amount?: number): voidvoidAdvances the bar and reveals it. Without an amount the configured trickle curve decides, which is what keeps an unknown wait moving without ever arriving.
HubLoadingBarService.resetreset(): voidvoidCancels everything at once — no completion animation, no pending callers, nothing on screen.
HubLoadingBarService.progressprogress: Signal<number>Signal<number> — the current fill, 0–100Current fill, 0–100. Safe to read during server-side rendering.
HubLoadingBarService.isActiveisActive: Signal<boolean>Signal<boolean> — true while at least one caller is waitingWhether any caller is still waiting — the honest “is the page loading?” question, regardless of whether the bar has decided to show itself.
HubLoadingBarService.isVisibleisVisible: Signal<boolean>Signal<boolean> — true only while the bar is paintedWhether the bar is actually painted. False during the grace period, and still true through the completion tail.

Templates

Make it yours — 7 template slots let you project custom markup.

NameDescriptionExample
Default Content SlotAnything projected between the tags renders below the message — a cancel action, a progress note, or a hint that the operation is taking longer than usual.<hub-loading message="Importing rows"><button type="button">Cancel</button></hub-loading>
provideHubLoadingRegisters application-wide defaults through the `HUB_LOADING_CONFIG` token — brand image, preferred variant, translated label — so `<hub-loading>` and `HubLoadingService` both start from them and individual call sites stay bare.providers: [provideHubLoading({ variant: 'ring', size: 'lg' })]
Bar Under The NavbarThe placement the bar is named after. `position: relative` on the navbar is what confines the overlay to it, and `placement="bottom"` hangs it off the lower edge.<nav class="navbar position-relative"> <hub-loading-bar mode="overlay" placement="bottom" /> </nav>
provideHubLoadingBarRouterRuns the bar for exactly the length of a navigation, including one a guard rejects or an error ends — the two cases that normally strand a hand-wired bar.providers: [provideRouter(routes), provideHubLoadingBarRouter()]
hubLoadingBarInterceptorHolds the bar open for the lifetime of every HTTP request. `finalize` balances it on success, on error and on cancellation alike.provideHttpClient(withInterceptors([hubLoadingBarInterceptor]))
withoutHubLoadingBarTakes one request out of the count. A poll on a timer would otherwise hold the bar open forever, and a progress bar that never finishes is worse than none.this.http.get('/api/heartbeat', { context: withoutHubLoadingBar() })
provideHubLoadingBarRegisters application-wide bar defaults through the `HUB_LOADING_BAR_CONFIG` token — accent, pacing, grace period, trickle curve, translated label.providers: [provideHubLoadingBar({ color: 'primary', delay: 120 })]