SvLoadingOverlay

A cover-a-container loading scrim: a translucent overlay with a centred spinner that sits on top of any positioned parent while its content loads or saves.

SvLoadingOverlay fills its nearest positioned ancestor (position: absolute; inset: 0) with a scrim + SvSpinner and an optional label. Drop it inside a position: relative wrapper so the content stays visible (optionally blurred) underneath while an async action is in flight - a save, a fetch, a recalculation.

Related: SvSpinner · SvSkeleton · SvResult

Installation

Add it with the CLI - this drops a ready-to-edit SvLoadingOverlay starter into your app:

Prefer to see it first? npx @svgrid/ui try loading-overlay opens it in a throwaway sandbox - no project needed.

Or install the package and import it directly. SvLoadingOverlay ships free in @svgrid/grid (dependency-free):

import { SvLoadingOverlay } from '@svgrid/grid'

Example

Open the live example: Layout & feedback primitives (Layout)

<script lang="ts">
  import { SvLoadingOverlay } from '@svgrid/grid'
  let loading = $state(false)
</script>

<div style="position: relative">
  <SvLoadingOverlay visible={loading} label="Saving…" />
  <!-- panel content -->
</div>

The wrapper must be positioned (relative / absolute) - the overlay pins itself to that box with inset: 0.

Props

Prop Type Default Description
visible boolean false Show the overlay. Nothing renders when false.
label string - Text under the spinner and the overlay's accessible name.
spinnerSize sm | md | lg | number lg Size passed through to the inner SvSpinner.
blur boolean false Blur the content behind the scrim.
children Snippet - Custom overlay content in place of the default spinner + label.

Accessibility

Over live content

The overlay covers its children rather than replacing them, so the layout does not jump when loading ends. blur is what stops the content behind reading as still-interactive.

<script lang="ts">
  import { SvLoadingOverlay, SvGrid, SvButton, type GridColumns } from '@svgrid/grid'

  type Person = { name: string; city: string }

  const people: Person[] = [
    { name: 'Ada Lovelace', city: 'London' },
    { name: 'Grace Hopper', city: 'New York' },
    { name: 'Linus Torvalds', city: 'Portland' },
  ]

  const columns: GridColumns<Person> = [
    { field: 'name', header: 'Name', width: 180 },
    { field: 'city', header: 'City', width: 140 },
  ]

  let busy = $state(false)

  function refresh() {
    busy = true
    setTimeout(() => (busy = false), 1200)
  }
</script>

<SvButton onclick={refresh}>Refresh</SvButton>

<SvLoadingOverlay visible={busy} label="Fetching rows..." blur>
  <SvGrid data={people} {columns} />
</SvLoadingOverlay>

See also