import * as React from 'react';
import { Progress, ProgressCircle } from '@/components/progress';
import type { ProgressCircleProps, ProgressProps } from '@/components/progress';
import { PALETTES } from './axis-values';
import type { Entry } from './types';
/**
* A value that climbs, so the width transition is visible rather than described.
*
* Named, with explicit `displayName`s, for `chrome/lib/codegen.ts` — see the note on
* `ControlledSortDemo` in `registry/data.tsx`.
*/
function useTicker() {
const [value, setValue] = React.useState(10);
React.useEffect(() => {
const id = setInterval(() => setValue((current) => (current >= 100 ? 0 : current + 10)), 700);
return () => clearInterval(id);
}, []);
return value;
}
function AnimatedBarDemo() {
const value = useTicker();
return ;
}
AnimatedBarDemo.displayName = 'AnimatedBarDemo';
function AnimatedCircleDemo() {
const value = useTicker();
return ;
}
AnimatedCircleDemo.displayName = 'AnimatedCircleDemo';
export const progress: Entry = {
slug: 'progress',
name: 'Progress',
group: 'Data display',
description:
'A determinate bar. Omit `value` and Radix reports the task as indeterminate to assistive technology.',
imports: { subpath: 'progress', names: ['Progress'] },
axes: {
colorPalette: PALETTES,
size: ['md', 'lg'],
},
defaults: { colorPalette: 'primary', size: 'md', value: 60 },
render: (props) => ,
matrices: [
{
title: 'Size × colorPalette',
description: 'CBAR draws the bar at two heights only: 6px and 9px.',
rows: 'size',
cols: 'colorPalette',
},
],
compositions: [
{
name: 'Values',
render: () => (
{[0, 25, 50, 75, 100].map((v) => (
))}
),
},
{
name: 'Animated',
description:
'The fill is a CSS transform transition, so a value that changes on an interval animates without any work here.',
render: () => ,
},
{
name: 'Indeterminate',
description:
'Omit `value` entirely. Radix drops `aria-valuenow`, which is what tells assistive technology the task has no measurable progress — do not fake it with `value={0}`.',
render: () => ,
},
],
};
export const progressCircle: Entry = {
slug: 'progress-circle',
name: 'ProgressCircle',
group: 'Data display',
description:
/* The subpath is named without the package in front of it: the copy line
above already prints the real one, and a rebranded kit would otherwise
have this sentence disagreeing with it. */
'The ring form of the same value. It ships from the same `progress` subpath as the bar, so it adds no export of its own.',
imports: { subpath: 'progress', names: ['ProgressCircle'] },
figma: { set: 'ProgressCircle', valueMap: { colorPalette: { tertiary: 'third' } } },
axes: {
colorPalette: PALETTES,
size: ['xs', 'sm', 'md', 'lg', 'xl'],
showValue: [true, false],
},
defaults: { colorPalette: 'primary', size: 'md', value: 65 },
render: (props) => ,
matrices: [
{
title: 'Size × colorPalette',
description:
'The centre label is on from md up and off below: a 24px ring has 16px of clear space, and "100%" at CBAR\'s 12px needs about 30px.',
rows: 'size',
cols: 'colorPalette',
},
],
compositions: [
{
name: 'Values',
render: () => (
{[0, 25, 50, 75, 100].map((v) => (
))}
),
},
{
name: 'Custom label',
description: 'formatValue receives the clamped 0–100 value.',
render: () => (
`${Math.round((v / 100) * 25)}/25`}
/>
),
},
{
name: 'Without the label',
description:
'`showValue={false}` keeps the ring and drops the number — for a dense row where the number would not be readable anyway. It is already off below `md`.',
render: () => (
),
},
{
name: 'Indeterminate',
description:
'No `value` at all: the arc detaches and spins, and Radix reports the task as indeterminate rather than as zero.',
render: () => ,
},
{
name: 'Animated',
description: 'The arc is a stroke-dashoffset transition, so a climbing value sweeps.',
render: () => ,
},
],
};