primitives

Spinner

Indeterminate loading indicator. SVG arc on web, ActivityIndicator on native, same prop shape.


Spinner is an indeterminate loading indicator. Five sizes, theme-colored by default, accessible by default.

Try it live

import { Spinner, Box, Stack, Text } from "@plyxui/primitives";

export default function App() {
return (
  <Box padding="lg" style={{ minHeight: "100vh" }}>
    <Stack direction="horizontal" gap={4} align="center">
      <Stack direction="vertical" gap={1} align="center"><Spinner size="xs" /><Text size="xs">xs</Text></Stack>
      <Stack direction="vertical" gap={1} align="center"><Spinner size="sm" /><Text size="xs">sm</Text></Stack>
      <Stack direction="vertical" gap={1} align="center"><Spinner size="md" /><Text size="xs">md</Text></Stack>
      <Stack direction="vertical" gap={1} align="center"><Spinner size="lg" /><Text size="xs">lg</Text></Stack>
      <Stack direction="vertical" gap={1} align="center"><Spinner size="xl" /><Text size="xs">xl</Text></Stack>
    </Stack>
  </Box>
);
}

API

import { Spinner } from "@plyxui/primitives";

<Spinner />

<Spinner size="lg" />
<Spinner size={48} />

<Spinner color={colors.primaryAccent} />

<Button loading={isSaving} iconLeading={<Spinner size="sm" />}>
  Save
</Button>

Sizes

TokenPixels
xs12
sm16
md (default)20
lg28
xl40

You can also pass a raw number for a custom size.

Accessibility

The Spinner has role="status" and an aria-label of "Loading". If your UI already has a visible "Loading…" text alongside, pass label={null} to keep screen readers from announcing the same state twice.

Props

PropTypeDefault
size"xs" | "sm" | "md" | "lg" | "xl" | number"md"
colorstringcolors.primaryOrange
thicknessnumber (fraction of size)0.12
labelstring | null"Loading"

Native

Wraps RN's ActivityIndicator. The xs/md/xl sizes map to raw pixel values (since RN's component takes pixels for custom sizes); sm and lg map to RN's built-in "small" and "large" because those have platform-tuned defaults that look right out of the box.