GrLoading
Indicates that a section or action is currently loading.
Overview
When to take it
- the content is already there and is being updated — a table is being re-requested, a form is being submitted: the old data is visible but unavailable;
- the wait is short —
delaydoes not show the spinner at all if the answer arrived quickly; - the whole screen has to be blocked —
fullscreenfor the duration of an operation that must not be interrupted; - the overlay is needed imperatively — the
v-loadingdirective instead of a component in the markup.
When to take something else
| Need | Take |
|---|---|
| There is no content at all yet | GrSkeleton |
| The share of what is done is known | GrProgressBar / GrProgressCircle |
| The wait is inside a button | GrButton with loading |
| Uploading a file | GrFileUpload |
Playground controls come from the API, not from hand
This component lives above the screen, not inside a canvas: a screen opens it, and the playground has nothing to open it from. The examples below show it at work.
0 changed· state is in the URL
<GrLoading>Label</GrLoading>Examples 3 each with a live demo and its code
A table recalculated in place
The layer lies on the nearest positioned ancestor, so
relativeon the block decides how far it reaches: the table waits, the period switch does not, and the old figures stay in view under the scrim.delaykeeps a fast answer — the week comes back in 120 ms — from flashing a spinner.Revenue by lineSubscriptions€76,900+6%Add-ons€9,450+3%Services€14,200+11%A card blocked while it saves
v-loadingcovers the card it sits on and also blocks it:aria-busyon the card andinerton its children, so Tab does not walk into fields nobody can see. Options come as an object — text, delay — and focus returns where it was when the layer closes.Payout accountWhere card payments are paid out every Monday. 13 / 18Switching a workspace
Switching reloads everything the app holds, so the whole screen waits:
fullscreencovers it. The default slot replaces the spinner with what the wait is about — which workspace is opening.Workspaces
API generated from the package · cannot drift
Props
| Prop | Type | default | Description |
|---|---|---|---|
text | string | undefined | undefined | The caption under the spinner. An empty string removes it entirely. By default — from the locale. |
zIndexVar | string | undefined | undefined | The name of the CSS variable of the layer — an escape hatch past `--gr-z-loading`. |
spinner | Component | undefined | undefined | A spinner component of your own instead of the default icon. |
spinnerClass | string | undefined | undefined | Extra classes for the wrapper of the spinner. |
spinnerSize | number | "xs" | "sm" | "md" | "lg" | undefined | 28 | The size of the spinner: the scale of the package or an arbitrary one in pixels. |
spinnerTone | GrIconTone | undefined | "neutral" | The tone of the spinner from the palette. |
animated | boolean | undefined | true | The rotation of the spinner. On by default. |
background | string | undefined | undefined | A `background-color` of your own. If it is set, the default `--gr-overlay-bg` scrim is removed. |
fullscreen | boolean | undefined | false | Cover the whole screen (`position: fixed`) instead of the nearest positioned ancestor. |
delay | number | undefined | 0 | The delay before showing, in milliseconds: a short load does not flash an overlay. |
customClass | string | undefined | undefined | Extra classes for the root of the overlay. |
Slots
| Slot | Type | Description |
|---|---|---|
default | any | The content of the panel as a whole instead of the spinner with a caption. |
Events
| Event | Signature | Description |
|---|---|---|
show | (event: "show"): void | — |
Types
Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.
import type { GrLoadingProps, GrLoadingEmits } from '@feugene/granularity/components/GrLoading'Filedist/types/components/GrLoading/config.d.ts
const grLoadingConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrLoading">;Filedist/types/components/GrLoading/safelist.d.ts
const grLoadingSafelist: string[];Filedist/types/components/GrLoading/GrLoading.vue.d.ts
interface GrLoadingProps {
text?: string;
spinner?: Component;
spinnerClass?: string;
spinnerSize?: GrIconSize | number;
spinnerTone?: GrIconTone;
animated?: boolean;
background?: string;
fullscreen?: boolean;
zIndexVar?: string;
delay?: number;
customClass?: string;
}interface GrLoadingEmits {
(e: 'show'): void;
}Usage from the library prose
Two modes
By default the overlay lies on the nearest positioned ancestor — that is the loading of a
piece of the page. fullscreen covers the whole screen: that is loading at the level of the
application.
The directive chooses the mode itself: target = document.body → fullscreen, otherwise
inline. To a container with position: static it temporarily gives relative, and to a
container with rounding overflow: hidden, so that the blurred backdrop does not come out of
the rounded shape.
The delay
delay (ms) postpones the showing. A request that answered faster than the delay does not
show the overlay at all — flickering is more irritating than the absence of an indicator.
<GrLoading v-if="pending" :delay="200" />The countdown starts from the mounting, that is, from the moment the loading started. While it is running, the content is not blocked: otherwise a fast request would silently freeze the form.
Accessibility
The overlay is a role="status" with aria-live="polite": the caption is read by a screen
reader at the moment it appears, without interrupting the user.
Covering it visually is not enough: without blocking, the tab goes into a form that is no
longer visible, and a screen reader reads it as an ordinary one. At the moment of showing,
the directive therefore declares the container aria-busy="true" and gives inert to its
other children — the subtree as a whole drops out of the tab order, out of pointer events and
out of the accessibility tree. On closing, inert is removed only from what it set itself,
and the focus returns to where it was if the user has not moved it themselves.
The declarative <GrLoading> does not dispose of its neighbours — it does not know them. If
blocking is needed on the same container, take the directive.
There is deliberately no focus trap inside the overlay: there is nothing to trap in it, and
the inert on the neighbours covers the task as a whole.
The layer
The full-screen mode sits on the --gr-z-loading token (1150) — above the modals, because
it blocks the whole application, and below the toasts, so as not to hide a notification about
a background error. The inline mode has nothing to do with the scale: z-10 is the order
inside its own container.
zIndexVar replaces the layer variable with one of your own — an escape hatch of the same
kind as in useFloating. The component does not accept a raw number: see docs/z-index.md.
The scrim
The dimming under the panel is the --gr-overlay-bg role of the theme, the same one
GrModal and GrDrawer use: a loading overlay has to look like the other modal layers and
to change density together with the theme.
The background prop sets a background-color of your own and cancels the scrim entirely —
it is needed when the overlay lies on an already dimmed surface.
The spinner and the content
spinnerSize and spinnerTone go through GrIcon — the scale of the icons and the text
tokens rather than pixels in the markup. spinner replaces the icon itself, and animated
switches the rotation off.
The slot replaces the content of the panel as a whole — progress with percentages, a button to cancel a long operation:
<GrLoading>
<GrProgressBar :value="percent" class="w-48" />
<GrButton size="xs" variant="outline" @click="abort">Cancel</GrButton>
</GrLoading>The caption comes from the locale by default (gr.loading.defaultText); text sets one of
your own, and an empty string removes it entirely.
The directive
const controller = createLoading({ target: '#report', text: 'Computing the report', delay: 200 })
controller.setText('Almost done')
controller.close()v-loading accepts either a boolean or an object of options (the same as the component’s,
plus target and fullscreen). Changing target or the mode recreates the overlay,
everything else is updated in place.
Props in this example