Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions apps/www/src/content/docs/components/progress/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
'use client';

import { getPropsString } from '@/lib/utils';

export const getCode = (props: any) => {
return `<Progress${getPropsString(props)} />`;
};

export const playground = {
type: 'playground',
controls: {
value: { type: 'number', initialValue: 40, min: 0, max: 100 },
variant: {
type: 'select',
initialValue: 'linear',
options: ['linear', 'circular']
},
min: { type: 'number', defaultValue: 0, min: 0, max: 99 },
max: { type: 'number', defaultValue: 100, min: 1, max: 100 }
},
getCode
};

export const directUsageDemo = {
type: 'code',
code: `<Flex direction="column" gap="large" style={{ width: "300px" }}>
<Progress value={40} />
<Progress value={70} />
<Progress value={100} />
</Flex>`
};

export const variantDemo = {
type: 'code',
tabs: [
{
name: 'Linear',
code: `<Flex direction="column" gap="large" style={{ width: "300px" }}>
<Progress value={15}>
<Flex justify="between">
<Progress.Label>Uploading...</Progress.Label>
<Progress.Value />
</Flex>
<Progress.Track />
</Progress>
</Flex>`
},
{
name: 'Circular',
code: `<Flex gap="large" align="center">
<Progress variant="circular" value={70}>
<Progress.Track />
<Progress.Value />
</Progress>
<Progress variant="circular" value={30}>
<Progress.Track />
<Progress.Value />
</Progress>
<Progress variant="circular" value={90}>
<Progress.Track />
<Progress.Value />
</Progress>
</Flex>`
}
]
};

export const customizationDemo = {
type: 'code',
tabs: [
{
name: 'Linear',
code: `<Flex direction="column" gap="large" style={{ width: "300px" }}>
<Progress value={60}>
<Progress.Track style={{ height: 2 }} />
</Progress>
<Progress value={60}>
<Progress.Track />
</Progress>
<Progress value={60}>
<Progress.Track style={{ height: 8 }} />
</Progress>
</Flex>`
},
{
name: 'Circular',
code: `<Flex gap="large" align="center">
<Progress variant="circular" value={60}>
<Progress.Track style={{ width: 48, height: 48 }} />
<Progress.Value />
</Progress>
<Progress variant="circular" value={60}>
<Progress.Track />
<Progress.Value />
</Progress>
<Progress variant="circular" value={60}>
<Progress.Track style={{ width: 96, height: 96, "--rs-progress-track-size": "2px" }} />
<Progress.Value />
</Progress>
<Progress variant="circular" value={60}>
<Progress.Track style={{ "--rs-progress-track-size": "8px" }} />
<Progress.Value />
</Progress>
</Flex>`
}
]
};

export const animatedDemo = {
type: 'code',
code: `function AnimatedProgress() {
const [value, setValue] = React.useState(0);

React.useEffect(() => {
const interval = setInterval(() => {
setValue((current) => {
if (current >= 100) return 0;
return Math.min(100, Math.round(current + Math.random() * 25));
});
}, 1000);
return () => clearInterval(interval);
}, []);

return (
<Flex gap="large" align="center">
<Progress value={value} style={{ width: 300 }}>
<Flex justify="between">
<Progress.Label>Uploading...</Progress.Label>
<Progress.Value />
</Flex>
<Progress.Track />
</Progress>
<Progress variant="circular" value={value}>
<Progress.Track />
<Progress.Value />
</Progress>
</Flex>
);
}`
};

export const withLabelsDemo = {
type: 'code',
code: `<Flex direction="column" gap="large" style={{ width: "300px" }}>
<Progress value={60}>
<Flex justify="between">
<Progress.Label>Uploading files...</Progress.Label>
<Progress.Value />
</Flex>
<Progress.Track />
</Progress>
<Progress value={85}>
<Flex justify="between">
<Progress.Label>Processing...</Progress.Label>
<Progress.Value />
</Flex>
<Progress.Track />
</Progress>
</Flex>`
};
93 changes: 93 additions & 0 deletions apps/www/src/content/docs/components/progress/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: Progress
description: Displays the completion progress of a task.
source: packages/raystack/components/progress
tag: new
---

import { playground, directUsageDemo, variantDemo, customizationDemo, animatedDemo, withLabelsDemo } from "./demo.ts";

<Demo data={playground} />

## Anatomy

Import and assemble the component:

```tsx
import { Progress } from '@raystack/apsara'

{/* Direct usage — renders track automatically */}
<Progress value={40} />

{/* Composable usage */}
<Progress value={40}>
<Progress.Label>Uploading...</Progress.Label>
<Progress.Value />
<Progress.Track />
</Progress>
```

## API Reference

### Root

The main container for the progress. Renders a default track when no children are provided. Set `value` to `null` for an indeterminate state.

<auto-type-table path="./props.ts" name="ProgressProps" />

### Label

Displays a label for the progress.

<auto-type-table path="./props.ts" name="ProgressLabelProps" />

### Value

Displays the formatted current value as a percentage.

<auto-type-table path="./props.ts" name="ProgressValueProps" />

### Track

Contains the indicator that visualizes the current value.

<auto-type-table path="./props.ts" name="ProgressTrackProps" />

## Examples

### Variant

The progress supports `linear` and `circular` variants.

<Demo data={variantDemo} />

### Direct Usage

The simplest way to use the progress. When no children are provided, it renders the track automatically.

<Demo data={directUsageDemo} />

### Customization

Customize the track for both variants. For linear, use `height` on the track. For circular, use `width`/`height` on the track to control the overall size and `--rs-progress-track-size` to control the stroke thickness.

<Demo data={customizationDemo} />

### Animated

Use controlled `value` to animate the progress indicator.

<Demo data={animatedDemo} />

### With Labels

Compose with `Progress.Label` and `Progress.Value` for additional context.

<Demo data={withLabelsDemo} />

## Accessibility

- Uses the `progressbar` ARIA role
- Sets `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes
- Supports indeterminate state when `value` is `null`
- Supports `aria-label` and `aria-valuetext` for screen readers
46 changes: 46 additions & 0 deletions apps/www/src/content/docs/components/progress/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export interface ProgressProps {
/**
* The current value. Set to `null` for indeterminate state.
* @default 0
*/
value?: number | null;

/**
* Minimum value.
* @default 0
*/
min?: number;

/**
* Maximum value.
* @default 100
*/
max?: number;

/**
* The visual style of the progress.
* @default "linear"
*/
variant?: 'linear' | 'circular';

/** Additional CSS class name. */
className?: string;
}

export interface ProgressLabelProps {
/** The label text content. */
children: React.ReactNode;

/** Additional CSS class name. */
className?: string;
}

export interface ProgressValueProps {
/** Additional CSS class name. */
className?: string;
}

export interface ProgressTrackProps {
/** Additional CSS class name. */
className?: string;
}
Loading