Atom
Spinner
Requires <UIProvider> — Getting Started →
Installation
Install just this component (copies the source into your project, no npm dependency)
npx orn-ui add spinnerOr install the whole package and import it
pnpm add orn-ui
import { Spinner } from 'orn-ui/spinner';Depends on:core (theme + icons)
Usage
- variant — `native` is the system indicator and the right default. `dots` and `ring` look identical on iOS and Android when that matters.
- fullscreen — `true` takes the whole area; set it to `false` for an inline spinner inside a row or a card.
- text — A short line under the indicator. Use it when the wait is long enough to need explaining.
- indicator — Your own node, when the brand asks for something the three variants do not cover.
Demo clip not recorded yet — see MEDIA.md
Variants
Default — a status message under the spinner
<Spinner text="Loading invoices..." fullscreen={false} />Custom look — dots and ring, identical on iOS and Android
<VariantRow>
<Spinner variant="dots" text="Fetching..." fullscreen={false} />
<Spinner variant="ring" text="Syncing..." fullscreen={false} />
</VariantRow>Sizes — small for inline use, large for a loading screen
<VariantRow>
<Spinner variant="ring" size="small" fullscreen={false} />
<Spinner variant="ring" size="large" fullscreen={false} />
</VariantRow>Custom color — matches your brand accent
<VariantRow>
<Spinner variant="dots" color="#00cae1" fullscreen={false} />
<Spinner variant="ring" color="#ff3b30" fullscreen={false} />
</VariantRow>Your own indicator — e.g. an avatar while a photo uploads
<Spinner
fullscreen={false}
text="Uploading..."
indicator={
<Avatar size={48} backgroundColor="#004cef20">
<Icon name="plus" size={24} color="#004cef" />
</Avatar>
}
/>No text — just the wait, next to a button or inline in a row
<View style={{ alignItems: 'center' }}>
<Spinner variant="ring" fullscreen={false} />
</View>Full demo source
const variants: VariantDef[] = [
{
label: 'Default — a status message under the spinner',
content: <Spinner text="Loading invoices..." fullscreen={false} />,
},
{
label: 'Custom look — dots and ring, identical on iOS and Android',
content: (
<VariantRow>
<Spinner variant="dots" text="Fetching..." fullscreen={false} />
<Spinner variant="ring" text="Syncing..." fullscreen={false} />
</VariantRow>
),
},
{
label: 'Sizes — small for inline use, large for a loading screen',
content: (
<VariantRow>
<Spinner variant="ring" size="small" fullscreen={false} />
<Spinner variant="ring" size="large" fullscreen={false} />
</VariantRow>
),
},
{
label: 'Custom color — matches your brand accent',
content: (
<VariantRow>
<Spinner variant="dots" color="#00cae1" fullscreen={false} />
<Spinner variant="ring" color="#ff3b30" fullscreen={false} />
</VariantRow>
),
},
{
label: 'Your own indicator — e.g. an avatar while a photo uploads',
content: (
<Spinner
fullscreen={false}
text="Uploading..."
indicator={
<Avatar size={48} backgroundColor="#004cef20">
<Icon name="plus" size={24} color="#004cef" />
</Avatar>
}
/>
),
},
{
label: 'No text — just the wait, next to a button or inline in a row',
content: (
<View style={{ alignItems: 'center' }}>
<Spinner variant="ring" fullscreen={false} />
</View>
),
},
];
return <VariantList variants={variants} />;Props
Also accepts testID, forwarded to the root node. It exists for end-to-end tests (Maestro drives the app by the accessibility tree) and has no effect on how the component looks or behaves.
| Name | Type | Default | Description |
|---|---|---|---|
size? | 'small' | 'large' | large | — |
color? | string | — | — |
text? | string | — | — |
fullscreen? | boolean | true | When false, doesn't take up flex:1 (useful inline, inside a button/row). |
variant? | 'native' | 'dots' | 'ring' | native | 'native' uses the system ActivityIndicator; 'dots' and 'ring' are custom indicators, identical on iOS and Android. |
indicator? | ReactNode | — | Fully custom indicator. Wins over `variant`. |