Demos
How to import
import { Progress } from '@fibrous/semi-ui-react';
Standard progress bar
Use stroke Property to control the filling color of the progress bar
Use Percent Property to control completed progress
Use size Property control progress bar size
Use aria-label Property to explain the specific role
If the preset size is not satisfied, You can pass height to customize the height of the progress bar through style property.
Code
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<div style={{ width: 200 }}>
<Progress percent={10} stroke="var(--semi-color-warning)" aria-label="disk usage" />
<br />
<Progress percent={25} stroke="var(--semi-color-danger)" aria-label="disk usage" />
<br />
<Progress percent={50} aria-label="disk usage" />
<br />
<Progress percent={80} aria-label="download progress" />
<br />
<Progress percent={80} size="large" aria-label="disk usage" />
<br />
<Progress percent={80} style={{ height: '8px' }} aria-label="disk usage" />
</div>
);
}Indeterminate progress bar
Set indeterminate when progress cannot be calculated. It supports both line and circle progress bars. When enabled, percent no longer controls the progress length and showInfo text is hidden.
Code
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<div style={{ width: 240 }}>
<Progress indeterminate aria-label="正在加载" />
<br />
<Progress indeterminate size="large" aria-label="正在加载" />
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 20 }}>
<Progress indeterminate type="circle" aria-label="正在加载" />
<Progress indeterminate type="circle" size="small" aria-label="正在加载" />
</div>
</div>
);
}Show percentage text
You can control whether to show percentage number through the showInfo property In addition, you can format the percentage text show through format.
Code
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<div style={{ width: 200 }}>
<Progress percent={10} stroke="var(--semi-color-warning)" showInfo aria-label="disk usage" />
<br />
<Progress percent={25} stroke="var(--semi-color-danger)" showInfo aria-label="disk usage" />
<br />
<Progress percent={50} showInfo aria-label="disk usage" />
<br />
<Progress percent={50} showInfo format={(percent) => percent * 10 + '‰'} aria-label="disk usage" />
</div>
);
}Vertical progress bar
You can use vertical progress bar by setting direction='vertical' If preset width is not satisfied, you can pass width to customize the width of the vertical progress bar through style property.
Code
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<div style={{ height: 100, display: 'flex' }}>
<Progress percent={10} direction="vertical" aria-label="disk usage" />
<Progress percent={25} direction="vertical" aria-label="disk usage" />
<Progress percent={50} direction="vertical" aria-label="disk usage" />
<Progress percent={80} direction="vertical" size="large" aria-label="disk usage" />
<Progress percent={80} direction="vertical" style={{ width: '8px' }} aria-label="disk usage" />
</div>
);
}Circular progress bar
Set type tocircle, the progress bar will be displayed in a ring shape. The default size of the progress bar is 72 x 72
Code
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<div>
<Progress percent={10} type="circle" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={25} type="circle" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={50} type="circle" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={80} type="circle" style={{ margin: 5 }} aria-label="disk usage" />
</div>
);
}You can modify it's width to control the size of the circular progress bar.
Code
import React from 'react';
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<React.Fragment>
<div>
<Progress percent={100} type="circle" width={100} style={{ margin: 5 }} aria-label="disk usage" />
</div>
<div>
<Progress percent={100} type="circle" width={100} style={{ margin: 5 }} stroke="var(--semi-color-danger)" aria-label="disk usage" />
</div>
</React.Fragment>
);
}Small circular progress bar
Small progress bar default size is 24 x 24.
Code
import React from 'react';
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<React.Fragment>
<Progress percent={10} type="circle" size="small" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={25} type="circle" size="small" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={50} type="circle" size="small" style={{ margin: 5 }} aria-label="disk usage" />
<Progress percent={80} type="circle" size="small" style={{ margin: 5 }} aria-label="disk usage" />
</React.Fragment>
);
}Dynamic change percent
The number in the text animates to the new percent. When percent changes again while the animation is running, the new animation starts from the number currently shown.
Code
import { useState } from 'react';
import { IconChevronLeft, IconChevronRight } from '@fibrous/semi-icons-react';
import { Progress, Button } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
const [percent, setPercent] = useState(40);
return (
<div>
<Progress percent={percent} showInfo aria-label="disk usage" />
<Button
aria-label="减少"
icon={<IconChevronLeft />}
theme="light"
onClick={() => {
setPercent(percent - 10);
}}
disabled={percent === 0}
/>
<Button
aria-label="增加"
icon={<IconChevronRight />}
theme="light"
onClick={() => {
setPercent(percent + 10);
}}
disabled={percent >= 100}
/>
</div>
);
}Code
import { useState } from 'react';
import { IconChevronLeft, IconChevronRight } from '@fibrous/semi-icons-react';
import { Progress, Button } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
const [cirPerc, setCirPerc] = useState(40);
return (
<div>
<div>
<Progress percent={cirPerc} type="circle" aria-label="disk usage" />
</div>
<Button
aria-label="减少"
icon={<IconChevronLeft />}
theme="light"
onClick={() => {
setCirPerc(cirPerc - 10);
}}
disabled={cirPerc === 0}
/>
<Button
aria-label="增加"
icon={<IconChevronRight />}
theme="light"
onClick={() => {
setCirPerc(cirPerc + 10);
}}
disabled={cirPerc >= 100}
/>
</div>
);
}Custom central text content
You can customize the central text by passing format function, and the argument of the format is the current percentage
If you don't need central text content, you can set showInfo to false or return an empty string directly in format
Code
import React from 'react';
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<React.Fragment>
<Progress percent={75} showInfo type="circle" format={(per) => per + 'Days'} style={{ margin: 10 }} aria-label="disk usage" />
<Progress percent={100} showInfo type="circle" format={() => 'Done'} style={{ margin: 10 }} aria-label="disk usage" />
<Progress percent={50} type="circle" showInfo={false} style={{ margin: 10 }} aria-label="disk usage" />
</React.Fragment>
);
}Round / square edges
With the strokeLinecap property, you can control the edge shape of the ring progress bar.
Code
import React from 'react';
import { Progress } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
return (
<React.Fragment>
<Progress percent={50} strokeLinecap="round" type="circle" style={{ margin: 10 }} aria-label="disk usage" />
<Progress percent={50} strokeLinecap="square" type="circle" style={{ margin: 10 }} aria-label="disk usage" />
</React.Fragment>
);
}Customise the progress bar color
The color of a specific percent can be customised by setting the stroke property
Code
import { useState } from 'react';
import { IconChevronLeft, IconChevronRight } from '@fibrous/semi-icons-react';
import { Progress, Button } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
const [percent, setPercent] = useState(10);
const strokeArr = [
{ percent: 20, color: 'red' },
{ percent: 40, color: 'orange-9' },
{ percent: 60, color: 'light-green-8' },
{ percent: 80, color: 'hsla(125, 50%, 46%, 1)' },
];
return (
<>
<div>
<Progress percent={percent} stroke={strokeArr} showInfo type="circle" width={100} aria-label="disk usage" />
<Progress percent={percent} stroke={strokeArr} showInfo style={{ margin: '20px 0 10px' }} aria-label="disk usage" />
</div>
<Button
aria-label="Decrease"
icon={<IconChevronLeft />}
theme="light"
onClick={() => {
setPercent(percent - 10);
}}
disabled={percent === 0}
/>
<Button
aria-label="Increase"
icon={<IconChevronRight />}
theme="light"
onClick={() => {
setPercent(percent + 10);
}}
disabled={percent === 100}
/>
</>
);
}Auto-completion of colour intervals
The gradient can be generated by setting the strokeGradient property to true, automatically fill the colour interval.
Code
import { useEffect, useState } from 'react';
import { IconChevronLeft, IconChevronRight } from '@fibrous/semi-icons-react';
import { Space, Progress, Button } from '@fibrous/semi-ui-react';
export default function ProgressDemo() {
const [percent, setPercent] = useState(65);
const [percentInterval, setPercentInterval] = useState(0);
useEffect(() => {
const timer = setTimeout(
() => {
setPercentInterval(percentInterval > 100 ? 0 : percentInterval + 3);
},
percentInterval === 0 || percentInterval > 100 ? 1200 : 290 - (percentInterval % 50) * 3
);
return () => clearTimeout(timer);
}, [percentInterval]);
const strokeArr = [
{ percent: 0, color: 'rgb(249, 57, 32)' },
{ percent: 50, color: '#46259E' },
{ percent: 100, color: 'hsla(125, 50%, 46%, 1)' },
];
const strokeArrReverse = [
{ percent: 0, color: 'hsla(125, 50%, 46%, 1)' },
{ percent: 50, color: '#46259E' },
{ percent: 100, color: 'rgb(249, 57, 32)' },
];
return (
<>
<Space spacing={20}>
<div>
<Progress percent={percentInterval} stroke={strokeArr} strokeGradient showInfo type="circle" width={100} aria-label="file download speed" />
</div>
<div>
<Progress percent={percentInterval} stroke={strokeArrReverse} strokeGradient showInfo type="circle" width={100} aria-label="file download speed" />
</div>
</Space>
<div style={{ width: '100%', margin: '20px 0 10px' }}>
<Progress percent={percent} stroke={strokeArr} strokeGradient showInfo size="large" aria-label="file download speed" />
</div>
<Button
aria-label="Decrease"
icon={<IconChevronLeft />}
theme="light"
onClick={() => {
setPercent(percent - 5);
}}
disabled={percent === 0}
/>
<Button
aria-label="Increase"
icon={<IconChevronRight />}
theme="light"
onClick={() => {
setPercent(percent + 5);
}}
disabled={percent === 100}
/>
</>
);
}API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| className | Class name of the root element. | string | "" |
| direction | Direction of the line progress bar: horizontal or vertical. | 'horizontal' | 'vertical' | "horizontal" |
| format | Formatting function. It receives the shown percentage, clamped to 0-100 and animated during transitions, and its return value is rendered in the center of a circle or on the right of a line. It runs on every render, even when showInfo is false. | Type(percent: number) => React.ReactNode | Type(percent: number) => `${percent}%` |
| indeterminate | Whether the progress is indeterminate. When on, percent no longer controls the length, the text is hidden and aria-valuenow is omitted. | boolean | false |
| motion | Whether the number in the text animates to the new percent. When off, it jumps to the target. | Motion | true |
| orbitStroke | Fill color of the track. When not set, the stylesheet decides it. | string | - |
| percent | Progress percentage. Values outside 0-100 are clamped. | number | 0 |
| ref | Reference to the root element (role="progressbar"). | TypeReact.Ref<HTMLDivElement> | - |
| showInfo | Whether to show the text: in the center of a circle, or on the right of a line. A circle with size small never shows the text. | boolean | false |
| size | Size: default, small (circle only) or large (line only). | Size | "default" |
| stroke | Fill color. An array is a list of { percent, color } intervals, where color is any CSS color or a Semi palette name such as blue or orange-9 (shade 5 when no shade is given). | string | StrokeArr | - |
| strokeGradient | Whether to generate gradient colors between the intervals. Takes effect only when stroke is an array of intervals. | boolean | false |
| strokeLinecap | Line cap of the circle progress bar: round or square. Has no effect on a line progress bar. | 'round' | 'square' | "round" |
| strokeWidth | Stroke width of the circle progress bar. | number | 4 |
| style | Style of the root element. | React.CSSProperties | {} |
| type | Type: line or circle. | 'line' | 'circle' | "line" |
| width | Diameter of the circle progress bar, effective only when type is circle. When not set, it is 24 for size small and 72 otherwise. | number | - |
aria-label, aria-labelledby, aria-valuetext, id and other native attributes are spread onto the root element (role="progressbar").
Accessibility
ARIA
- Progress has a
progressbarrole to indicate that it is a progress bar component. - Progress will automatically set
aria-valuenowas the progress percentage (percent) passed to the component to ensure that the screen reader can get the correct percentage value. Whenindeterminate=true,aria-valuenowis omitted because the current progress value is unknown. In addition, Progress supports incomingaria-valuetext. When you pass in, according to W3C specifications,aria-valuetextwill be used and consumed by screen readers instead ofaria-valuenow - Progress support
aria-label,aria-labelledby- When there is a description element about the role of Progress outside of Progress, you can explicitly specify that the id of certain elements is the label of Progress through
aria-labelledby - Otherwise, you should use aria-label to explain the specific meaning of the value represented by Progress
- When there is a description element about the role of Progress outside of Progress, you can explicitly specify that the id of certain elements is the label of Progress through
// good case
<p id="progressbar-label">Disk Usage</p>
<Progress aria-labelledby="progressbar-label" percent={80} />
// good case
<Progress aria-label='Percent of disk usage' percent={80} />
<Progress aria-label='Percent of file downloaded' percent={80} />
// usage of aria-valuetext
<Progress aria-label='Percent of disk usage' percent={80} aria-valuetext="Step 2: Copying files... "/>
Content Guidelines
- If the progress bar process is complicated, or there is a long waiting time, you can use the help text to explain. This lets the user know what progress is happening.
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $color-progress_default-bg | var(--semi-color-fill-0) | 默认背景色 |
| $color-progress_track_inner-bg | var(--semi-color-success) | 默认进度色 |
| $color-progress_line_text-text | var(--semi-color-text-0) | 百分比文本文字颜色 |
| $color-progress_circle-text | var(--semi-color-text-0) | 环形进度百分比文字颜色 |
| $motion-progress-transition_duration | 0.3s | 进度条动画时长 |
| $motion-progress-transition_timing_function | cubic-bezier(0.62, 0.05, 0.36, 0.95) | 进度条动画曲线 |
| $height-progress_horizontal | 4px | 水平进度条高度 |
| $height-progress_horizontal_large | 6px | 大尺寸水平进度条高度 |
| $spacing-progress_line_text-marginLeft | $spacing-base | 水平进度条百分比文本左侧外边距 |
| $spacing-progress_vertical-marginX | $spacing-extra-tight | 垂直进度条水平方向外边距 |
| $spacing-progress_horizontal-marginY | $spacing-extra-tight | 水平进度条垂直方向外边距 |
| $spacing-progress_vertical_line_text-marginTop | $spacing-tight | 垂直进度条百分比文本顶部外边距 |
| $font-progress_line_text-fontWeight | 600 | 百分比文本字重 |
| $width-progress_line_text | 45px | 百分比文本最小宽度 |
| $width-progress_vertical | 4px | 垂直进度条宽度 |
| $width-progress_vertical_large | 6px | 大尺寸垂直进度条宽度 |
| $radius-progress_track | var(--semi-border-radius-small) | 背景圆角大小 |
| $radius-progress_track_inner | var(--semi-border-radius-small) | 进度条圆角大小 |