Spinner

Primitives

Animated loading indicator with three variants (circle, dots, pulse), four size presets, speed control, all theme color tokens, and an optional full-screen overlay.

GitHub

Installation

bash
1
npx native-mate add spinner
npm 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

PropTypeDefaultDescription
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.
labelstring"Loading"Accessible description for screen readers.
overlaybooleanfalseRenders the spinner centered over a semi-transparent full-parent overlay.
overlayOpacitynumber0.6Opacity 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

FeatureDetail
RoleaccessibilityRole="progressbar" is set automatically.
LabelThe label prop is read by screen readers (default: "Loading"). Pass a descriptive string when context matters.
Live regionaccessibilityLiveRegion="polite" announces the spinner to screen readers without interrupting current speech.