import { useState } from "react";
import { Text, View } from "react-native";
import { Button } from "@/component-lib/button";
import { useKitTheme } from "@/component-lib/shared/native";
import { Spinner } from "@/component-lib/spinner";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
export function SpinnerDemo() {
const { tokens } = useKitTheme();
const [busy, setBusy] = useState(false);
return (
<>
<Section title="Spinner · sizes">
<Row>
<Spinner size="xs" />
<Spinner size="sm" />
<Spinner size="md" />
<Spinner size="lg" />
<Spinner size="xl" />
<Spinner size={56} color={tokens.success} />
</Row>
</Section>
<Section title="Spinner · dots and labels">
<Row>
<Spinner variant="dots" size="lg" />
<Spinner variant="dots" size="xl" color={tokens.danger} />
<Spinner showLabel label="Fetching invoices…" />
<Spinner variant="dots" showLabel />
</Row>
</Section>
<Section title="Spinner · covering content (delay 150 ms, min 600 ms)">
<Spinner loading={busy} delay={150} minDuration={600} style={{ borderRadius: tokens.radius }}>
<View style={{ padding: 16, borderRadius: tokens.radius, borderWidth: 1, borderColor: tokens.border, gap: 10 }}>
<Text style={{ color: tokens.fg, fontSize: tokens.fontSize, fontWeight: "600" }}>Monthly report</Text>
<Text style={{ color: tokens.muted, fontSize: tokens.fontSize }}>
While loading, this panel takes no touches and is hidden from screen readers.
</Text>
<Button variant="outline" size="sm" onPress={() => setBusy(true)}>
Refresh
</Button>
</View>
</Spinner>
<Button variant="secondary" onPress={() => setBusy((b) => !b)}>
{busy ? "Stop loading" : "Start loading"}
</Button>
</Section>
</>
);
}Install
npx @grampro/kit@native add SpinnerUsage
import { Spinner } from "@/component-lib/spinner";
<Spinner loading={pending} delay={200} label="Loading invoices" />Props
SpinnerProps
| Prop | Type | Description |
|---|---|---|
loading | boolean | Default true. With children, the spinner covers them while this is true. |
size | SpinnerSize | number | Default md (24 dp); a number is dp. |
variant | SpinnerVariant | Default ring. |
color | string | Colour of the indicator. Default: the accent colour (the web uses currentColor). |
label | string | What screen readers announce. Default "Loading". |
showLabel | boolean | Show the label next to the spinner. |
delay | number | Milliseconds to wait before showing, so fast work doesn't flash. Default 0. |
minDuration | number | Once shown, stay at least this many milliseconds. Default 0. |
children | ReactNode | Content to cover while loading. It stops taking touches and is hidden from screen readers. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; status: StyleProp<ViewStyle>; indicator: StylePro… | |
localeText | Partial<SpinnerLocaleText> |
Also accepts the props of Omit<ViewProps, "children" | "style">.
Native and web
- Takes a
color(native has nocurrentColor); defaults to the accent. - Web version: Spinner on the web.