Spinner
PrimitivesAnimated loading indicator with three variants (circle, dots, pulse), four size presets, speed control, all theme color tokens, and an optional full-screen overlay.
Installation
bash
1
npx native-mate add spinnernpm deps: react-native-reanimated
Examples
#FAFAFA
Radius100%
Usage
tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { Spinner } from '~/components/ui/spinner'
// Variants
<Spinner variant="circle" />
<Spinner variant="dots" />
<Spinner variant="pulse" />
// Sizes
<Spinner size="sm" />
<Spinner size="md" />
<Spinner size="lg" />
<Spinner size={56} />
// Colors
<Spinner color="primary" />
<Spinner color="success" />
<Spinner color="destructive" />
<Spinner color="#a78bfa" />
// Speed
<Spinner speed="fast" />
<Spinner speed="slow" />
<Spinner speed={400} /> // custom ms
// Overlay — covers nearest positioned parent
<View style={{ position: 'relative' }}>
<YourContent />
{loading && <Spinner overlay overlayOpacity={0.5} />}
</View>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "circle"|"dots"|"pulse" | "circle" | Animation style. |
| size | "sm"|"md"|"lg"|number | "md" | Preset (16/24/40 dp) or explicit dp. |
| color | "primary"|"foreground"|"muted"|"destructive"|"success"|"warning"|string | "primary" | Fill color — token or raw value. |
| speed | "slow"|"normal"|"fast"|number | "normal" | Cycle duration. Number = ms per full cycle. |
| label | string | "Loading" | Accessible description for screen readers. |
| overlay | boolean | false | Renders the spinner centered over a semi-transparent full-parent overlay. |
| overlayOpacity | number | 0.6 | Opacity of the overlay backdrop. |
Example
tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { useState } from 'react'
import { Spinner } from '~/components/ui/spinner'
import { Button } from '~/components/ui/button'
import { View } from 'react-native'
export function SpinnerExample() {
const [loading, setLoading] = useState(false)
return (
<View style={{ gap: 24, padding: 16 }}>
<View style={{ flexDirection: 'row', gap: 24, alignItems: 'center' }}>
<Spinner variant="circle" color="primary" />
<Spinner variant="dots" color="success" />
<Spinner variant="pulse" color="warning" />
</View>
<View style={{ position: 'relative', height: 120, backgroundColor: '#0f0f11', borderRadius: 12 }}>
{loading && <Spinner overlay label="Processing…" />}
<Button onPress={() => setLoading(l => !l)} style={{ margin: 16 }}>
{loading ? 'Hide overlay' : 'Show overlay'}
</Button>
</View>
</View>
)
}Accessibility
| Feature | Detail |
|---|---|
| Role | accessibilityRole="progressbar" is set automatically. |
| Label | The label prop is read by screen readers (default: "Loading"). Pass a descriptive string when context matters. |
| Live region | accessibilityLiveRegion="polite" announces the spinner to screen readers without interrupting current speech. |