Activity Rings

Pro

One to three concentric goal rings that fill in a quick cascade and lap again past 100%. Closing a ring makes it glow brightly before settling, as a small reward. Room in the centre for a figure.

Preview

Installation

npx @lumioui/cli add pro/activity-rings

Usage

import { ActivityRings } from "@/components/ui/activity-rings/activity-rings";
<ActivityRings />

Examples

Daily rings

A fitness app's daily summary card.

Habit week

A meditation app's single daily goal.

Friends

The friends tab of a fitness app.

Workout complete

The end of an outdoor ride.

API reference

Prop Type Default
rings* ActivityRing[]

One to three rings, outermost first. Extra rings are ignored.

—
size number

Square size in pt. Default 200.

200
strokeWidth number

Ring thickness. Default ~11% of size.

—
gap number

Space between rings. Default scales with the stroke.

—
animate boolean

Fill on mount and glide between values. Default true.

true
delay number

Extra delay before the first ring fills — stagger a row of rings.

0
haptics boolean

Haptic when a ring closes. Default true.

true
onRingClose (index: number, ring: ActivityRing) => void

A ring crossed its goal (fires after the fill lands).

—
onRingResolve (index: number, ring: ActivityRing) => void

A closed ring has held its moment (~690ms after onRingClose) — resolve captions here.

—
rewardLight boolean

Brighten a pool of the closing ring's light behind the stack. Turn it off for small rings in rows and lists. Default true.

true
children React.ReactNode

Centre slot — a figure, an icon. Hidden from screen readers (the root label covers it).

—
accessibilityLabel string

Screen-reader label. Default reads every ring.

—
className string —