import { useEffect, useState } from "react";
import { Text } from "react-native";
import { Button } from "@/component-lib/button";
import { CircularProgress, Progress } from "@/component-lib/progress";
import { useKitTheme } from "@/component-lib/shared/native";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
export function ProgressDemo() {
const { tokens } = useKitTheme();
const [value, setValue] = useState(35);
const [running, setRunning] = useState(false);
useEffect(() => {
if (!running) return;
const timer = setInterval(() => {
setValue((v) => {
if (v >= 100) {
setRunning(false);
return 100;
}
return Math.min(100, v + 7);
});
}, 300);
return () => clearInterval(timer);
}, [running]);
return (
<>
<Section title="Progress · bar">
<Progress label="Uploading statement.pdf" value={value} showValue />
<Progress label="Storage" value={3.2} max={8} showValue valueText="3.2 GB of 8 GB" variant="warning" />
<Progress label="Sync" value={100} showValue variant="success" size="lg" />
<Progress label="Failed import" value={62} showValue variant="danger" size="sm" />
<Progress label="Preparing export" value={null} showValue />
<Progress aria-label="No header" value={value} />
</Section>
<Section title="Progress · ring">
<Row>
<CircularProgress value={value} showValue />
<CircularProgress value={12} size={56} thickness={6} showValue variant="danger" />
<CircularProgress value={50} size={56} thickness={6} showValue variant="warning" />
<CircularProgress value={88} size={64} thickness={8} showValue variant="success" />
<CircularProgress value={null} />
<CircularProgress value={70} size={56}>
<Text style={{ color: tokens.fg, fontSize: 12, fontWeight: "700" }}>7/10</Text>
</CircularProgress>
</Row>
</Section>
<Row>
<Button
onPress={() => {
setValue(0);
setRunning(true);
}}
>
Run upload
</Button>
<Button variant="secondary" onPress={() => setValue((v) => Math.max(0, v - 10))}>
−10
</Button>
<Button variant="secondary" onPress={() => setValue((v) => Math.min(100, v + 10))}>
+10
</Button>
</Row>
</>
);
}Install
npx @grampro/kit@native add ProgressUsage
import { Progress, CircularProgress } from "@/component-lib/progress";
<Progress label="Uploading statement.pdf" value={35} showValue />
<CircularProgress value={88} variant="success" showValue />Props
ProgressProps
| Prop | Type | Description |
|---|---|---|
value | number | null | How far along. null means the length is not known yet. |
max | number | What value is measured against. Default 100. |
label | ReactNode | Names the bar. Shown above it, and used as the accessible name. |
showValue | boolean | Show the percentage beside the label. |
valueText | ReactNode | Replace what is shown and read, e.g. "3.2 MB of 8 MB". |
variant | ProgressVariant | Default accent. |
size | ProgressSize | Default md. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; header: StyleProp<ViewStyle>; label: StyleProp<Te… | |
localeText | Partial<ProgressLocaleText> |
Also accepts the props of Omit<ViewProps, "children" | "style" | "role">.
CircularProgressProps
| Prop | Type | Description |
|---|---|---|
value | number | null | |
max | number | |
size | number | Diameter in dp. Default 44. |
thickness | number | Ring thickness in dp. Default 4. |
variant | ProgressVariant | |
label | string | Names the ring for assistive technology. |
showValue | boolean | Print the percentage in the middle, or your own node. |
children | ReactNode | |
style | StyleProp<ViewStyle> | |
styles | Partial<{ root: StyleProp<ViewStyle>; track: StyleProp<ViewStyle>; bar: StyleProp<ViewS… | |
localeText | Partial<ProgressLocaleText> |
Native and web
- Rings are drawn with Views, no SVG; their ends are square.
- Web version: Progress on the web.