Progress RingiOS
Circular progress ring with animated stroke arc, center slot and indeterminate spin.
$ npx lumioui add progress-ring
import { ProgressRing } from "@/components/ui/progress-ring/progress-ring";
Files installed into your repo
components/ui/progress-ring/progress-ring.tsx
Native packages required
@lumioui/core@latestreact-native-reanimated@*react-native-svg@*
Props8
| value? | number | 0–100. Ignored while `indeterminate` is set. |
| size? | number | Square size in px. Default 96. |
| strokeWidth? | number | Ring stroke width in px. Default 8. |
| color? | keyof ColorTokens | Theme color token for the arc. Default "primary". |
| indeterminate? | boolean | Unknown progress — renders a spinning arc segment instead of the fill. |
| label? | string | Accessible label. Default "Progress, N%" (or "Loading" when indeterminate). |
| children? | React.ReactNode | Center slot — label, icon, or any content rendered inside the ring. |
| className? | string | |
Progress Ring — Indeterminateindeterminate.tsx
Live preview offline the relay is unreachable — check back shortly
progress-ring/variants/indeterminate.tsx open Circular progress ring with animated stroke arc, center slot and indeterminate spin.
import { ProgressRingIndeterminate } from "@/components/ui/progress-ring/variants/indeterminate";
export function Example() {
return (
<ProgressRingIndeterminate />
);
}
import * as React from "react";
import { View } from "react-native";
import { ProgressRing } from "../progress-ring";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** ProgressRingIndeterminate — syncing card with a spinning ring. */
export function ProgressRingIndeterminate() {
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full flex-row items-center gap-3 rounded-2xl p-4">
<ProgressRing indeterminate size={44} strokeWidth={5} />
<View className="flex-1">
<Text className="text-sm font-semibold text-foreground">Syncing health data</Text>
<Text variant="muted" className="text-xs">Apple Health · 42 records queued</Text>
</View>
</Glass>
</View>
);
}
Progress Ring — Labeledlabeled.tsx
Live preview offline the relay is unreachable — check back shortly
progress-ring/variants/labeled.tsx open Circular progress ring with animated stroke arc, center slot and indeterminate spin.
import { ProgressRingLabeled } from "@/components/ui/progress-ring/variants/labeled";
export function Example() {
return (
<ProgressRingLabeled />
);
}
import * as React from "react";
import { View } from "react-native";
import { ProgressRing } from "../progress-ring";
import { Icon } from "../../icon/icon";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
/** ProgressRingLabeled — daily goal ring staged in an activity card with stat rows. */
export function ProgressRingLabeled() {
const [value, setValue] = React.useState(34);
React.useEffect(() => {
const id = setInterval(() => {
setValue((v) => (v >= 92 ? 34 : v + 6));
}, 1400);
return () => clearInterval(id);
}, []);
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full gap-3 rounded-2xl p-4">
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold">Today · Activity</Text>
<Text variant="muted" className="text-xs">Lumo Health</Text>
</View>
<View className="flex-row items-center gap-4">
<ProgressRing value={value} size={84} strokeWidth={9}>
<View className="items-center">
<Text className="text-lg font-bold tabular-nums text-foreground">{value}%</Text>
</View>
</ProgressRing>
<View className="flex-1 gap-0.5">
<Text className="text-sm font-semibold text-foreground">Move goal</Text>
<Text variant="muted" className="text-xs">510 / 620 kcal · closes at 100%</Text>
</View>
</View>
<View className="flex-row gap-2 border-t border-border pt-3">
{[
["map-pin", "km", "4.8"],
["zap", "kcal", "510"],
["clock", "mins", "38"],
].map(([icon, label, val]) => (
<Glass interactive key={label} curvature="edge" className="flex-1 items-center gap-1 rounded-xl py-2.5">
<Icon name={icon as never} size="sm" color="mutedForeground" />
<Text variant="small" className="tabular-nums">{val}</Text>
<Text variant="muted" className="text-xs">{label}</Text>
</Glass>
))}
</View>
</Glass>
</View>
);
}