IslandNumber and IslandProgress
Content primitives that animate a changed number or a moving bar on the island's clock, as a live status activity's content does.
import { IslandNumber, IslandProgress, numberMotion } from "@/lib/island";
Both run on the island’s clock, so captures and stepped clocks see the same frames, and both follow the provider’s reduced-motion setting. Use them inside activity content; outside a provider they use a requestAnimationFrame clock and the system’s setting. When to use them rather than a crossfade is in Numbers and progress.
<IslandNumber>
Text whose changed characters turn over with a blur when value changes.
import { IslandNumber } from "@/lib/island";
export const Percent = ({ percent }: { percent: number }) => (
<IslandNumber value={`${percent}%`} style={{ fontSize: 34, fontWeight: 700, color: "#0a84ff" }} />
);
import type { CSSProperties } from "react";
interface IslandNumberProps {
value: number | string;
className?: string;
style?: CSSProperties;
}
valuenumber | string
The value. Numbers render with toString(); pass a string such as "4:07" to format it yourself.
number | stringclassName?string
Class on the wrapper.
stringstyle?CSSProperties
Style on the wrapper: font size, weight, colour.
CSSPropertiesThe old and new text are aligned from the right, and only the characters that changed move. Use tabular figures (fontVariantNumeric: "tabular-nums") so the width holds still. The wrapper is an inline-flex with an aria-label of the whole text; screen readers read the value once, not per digit. Because it is not plain text, a slot too narrow for it clips it rather than ending it in an ellipsis.
numberMotion holds the timing, measured on the simulator: the old character shrinks to 0.7 and blurs from 0.03 to 0.21 s, then fades out by 0.26 s; the new one starts at 0.2 s, fades in within 0.08 s, grows from 0.72 and is sharp by about 0.48 s. Under reduced motion the text changes with a plain fade.
<IslandProgress>
A capsule bar whose fill springs to each new value.
import { IslandProgress } from "@/lib/island";
export const Charge = ({ level }: { level: number }) => <IslandProgress value={level} color="#30D158" track="#414141" height={8} />;
import type { CSSProperties } from "react";
import type { SpringConfig } from "@/lib/island";
interface IslandProgressProps {
value: number;
color?: string;
track?: string;
height?: number;
radius?: number;
spring?: SpringConfig;
className?: string;
style?: CSSProperties;
}
valuenumber
Fill from 0 to 1.
numbercolor?string
Fill colour.
string"#30D158"track?string
Track colour.
string"#414141"height?number
Bar height in px.
number8radius?number
Corner radius in px.
numberhalf the heightspring?{ response, dampingFraction }
How the fill moves to a new value, fitted on the simulator's bar.
{ response, dampingFraction }{ response: 0.97, dampingFraction: 0.74 }className?string
Class on the track.
stringstyle?CSSProperties
Style on the track.
CSSPropertiesThe track is a progressbar with aria-valuenow from 0 to 100. If you wrap it in your own labelled progress bar, hide this one with aria-hidden, as the content kit’s LinearProgress does. Under reduced motion the fill eases to the new value over 0.2 s with no overshoot.