Marble UI
← Components

Loading Overlay

Preview: Default

Wraps content and covers it with a blurred overlay + spinner while `loading`; marks the region aria-busy and inert. If focus was inside, it moves to the region while loading (inert content can't hold it) and returns afterwards.

Import

import { LoadingOverlay } from '@marbleui/ui'

Props

<LoadingOverlay>

PropTypeDefaultDescription
children *requiredReactNode—
loading *requiredboolean—
classNamestring—
labelstring'Loading'

Usage notes

Covers a region with a blurred overlay and spinner while it saves or refreshes, keeping current content in place. For a first load with nothing to show use Skeleton; for a single action use Button with isPending.

<LoadingOverlay loading={isSaving} label="Saving" className="rounded-xl border border-border">
  <ProfileForm />
</LoadingOverlay>
  • While loading is true the wrapper has aria-busy and the content is inert: it can’t be clicked or focused, and assistive tech skips it.
  • If focus is inside when loading starts (say, on the Save button that started the save), it moves to the wrapper, and returns to that control when loading ends, as long as it’s still there and focus hasn’t moved elsewhere.
  • label (default “Loading”) names the spinner and shows under it. The overlay isn’t a live region, so announce the outcome separately, for example with toast.
  • The overlay inherits the wrapper’s corner radius, so put rounding on className.
Example source · show
import { useState } from 'react'
import { Button } from '../button'
import { TextField } from '../text-field'
import { LoadingOverlay } from './loading-overlay'

function Demo() {
  const [loading, setLoading] = useState(false)
  return (
    <LoadingOverlay loading={loading} label="Saving" className="w-80 rounded-xl border border-border bg-surface">
      <form className="flex flex-col gap-3 p-4" onSubmit={(e) => { e.preventDefault(); setLoading(true); setTimeout(() => setLoading(false), 1800) }}>
        <TextField label="Name" defaultValue="Maya Chen" /><TextField label="Email" defaultValue="maya@acme.com" />
        <Button type="submit">Save</Button>
      </form>
    </LoadingOverlay>
  )
}
export const styles = { Default: Demo }

Source: packages/ui/src/loading-overlay/loading-overlay.tsx

Catalog

Category
feedback
Priority
Extra
Primitive
composed