Skip to documentation

Spin

Lightweight loading indicator with size presets, a determinate progress ring, a network variant for AI work, and a children overlay mode.

import { Spin } from '@lobehub/ui/base-ui';
Feedback

Basic

Loading preview

APIs

Spin properties
children
null | string | number | bigint | false | true | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>
indicator
null | string | number | bigint | false | true | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>
percent
number
ref
null | (instance: HTMLDivElement | null) => void | (() => VoidOrUndefinedOnly) | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES] | RefObject<HTMLDivElement | null>

Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).

size
number | 'large' | 'middle' | 'small'

Defaults to "middle".

spinning
boolean

Defaults to true.

style
CSSProperties
tip
null | string | number | bigint | false | true | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>
variant
'default' | 'network'

Defaults to "default".

Also accepts all native HTML and ARIA attributes.

Spin renders a native <div>. All standard div HTML attributes including className, style, data-*, and ref are forwarded to the root element.

Sizes

size accepts small (14px), middle (20px, default), large (32px), or any raw pixel number.

Determinate progress

Pass percent (0–100) with the default variant to render a progress ring driven by stroke-dashoffset instead of the spinning glyph.

Network variant

variant="network" renders a layered-network glyph: nodes pulse, particles flow between layers, and a dashed ring rotates. Every animated property is transform or opacity, so it runs on the compositor and stays static under prefers-reduced-motion.

Use it only when the user is waiting on a model or agent. Plain network requests use the default variant.

Which indicator to use

Waiting onComponentSize
A button or icon actionButton loading / ActionIcon loadingfollows the button
Background sync next to a title or list itemSpinsmall
A model or agent (reasoning, tool call, task step)Spin variant="network"small inline, middle inside a card
The first token of a chat messageLoadingDots from @lobehub/ui/chat12
A panel whose layout is unknownSpin variant="network" centeredlarge
A panel whose layout is knownSkeleton—
Existing content being replacedSpin wrapping childrenmiddle
The app itselfBrandLoading from @lobehub/ui/brand40

Do not hand-roll spinners, use Icon spin, antd Spin, or third-party loading packages.

Overlaying content

When children is provided, Spin wraps it in a relative container and overlays a centered spinner (plus optional tip) on top while spinning is true. Set spinning={false} to render only the children.

Migrating from antd Spin

TSX
import { Spin } from '@lobehub/ui/base-ui';

<Spin spinning={loading} tip="Loading…">
  <Content />
</Spin>;

delay and fullscreen are not supported; gate spinning yourself and use Spin inside your own fullscreen container if needed.

antd's size="default" becomes size="middle".