Yugen UI

LoadingOverlay & useSpinDelay

Show loaders at the right moment and only over the region that is loading: no flash for fast responses, no flicker for slow ones.

useSpinDelay(loading, { delay, minDuration }) only turns the loader on when the wait lasts longer than delay (300ms by default), and once it is shown keeps it for at least minDuration (500ms). LoadingOverlay is built on this hook: it covers a region with a dimmed surface, a Spinner and a label while the old content keeps its place underneath. The region gets aria-busy and the label is announced through a live region.
Yugen Labs · experimentalThis component is outside SemVer: its API can change in a minor release, and What's new says so. Versioning policy
  • ORD-1024 · Alex Chen$1,250.00
  • ORD-1025 · Maria Garcia$860.00
  • ORD-1026 · Sam Lee$2,040.00

Updated at 7:36:14 PM

Import

Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.

TSX
// npm install yugen-uiimport { LoadingOverlay, useSpinDelay } from "yugen-ui";

Variants

Each tile is a standalone example: hover to copy, or press Code to see the source.

No delayLoads: 0
useSpinDelayLoads: 0

With and without useSpinDelay

Choose “Fast” and click “Load” a few times: the left panel flashes a spinner for 150ms, the right one doesn't change. Choose “Slow”: the right panel waits 300ms, then stays steady.

October revenue

$128,400

Up 12% from last month

Keep old content under the overlay

When refreshing data that is already on screen, dim it with an overlay instead of replacing it with a skeleton, so people can still read the old numbers.

Saved

Small indicators need a delay too

The “Saving…” line of an autosave uses the same useSpinDelay; a fast save only ever shows “Saved”.

Usage

Do
  • Wrap every loader (spinner, overlay, “Saving…”) in useSpinDelay so responses under 300ms don't cause a flash.
  • Cover only the region that is loading, and keep the old content when refreshing data that is already shown.
  • Set aria-busy on the loading region and say in words what is happening (“Refreshing…”).
Don't
  • Don't cover the whole page for a local action.
  • Don't hide a loader a few dozen milliseconds after it appears. Keep minDuration.
  • Don't move focus into the overlay. Focus stays where people are working.

Props

Prop · TypeDefaultDescription
useSpinDelay(loading, options)(boolean, SpinDelayOptions) => booleanDefault: —Returns true when the loader should be shown.
options.delaynumberDefault: 300Wait (ms) before showing; if the work finishes sooner, nothing is shown.
options.minDurationnumberDefault: 500Minimum time (ms) the loader stays once shown.
LoadingOverlay.loadingbooleanDefault: —The region is loading; aria-busy updates right away, the overlay follows delay.
labelReactNodeDefault: "Loading…"Label under the Spinner; a string label is announced through a live region when the overlay appears.
delay / minDurationnumberDefault: 0 / 500 when delay is setPassed to useSpinDelay.
spinnerSizeSpinnerSizeDefault: "medium"Spinner size.
overlayClassNamestringDefault: —Class for the overlay (opacity, padding…).

Messages

Text built into the component: labels, aria-labels, screen reader announcements.

English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.

messages.loadingOverlay

Key · TypeDefault (English)messagesVi
labelstring

Nhãn dưới Spinner, cũng là câu đọc cho trình đọc màn hình.

Default (English)"Loading…"messagesVi"Đang tải…"
announcementstring

Câu đọc khi label không phải chuỗi.

Default (English)"Loading"messagesVi"Đang tải"