反馈类

进度条

用于展示用户操作的当前进度和状态,一般在操作耗时较长时使用。也可用来表示任务/对象的完成度

代码演示

如何引入

import { Progress } from '@fibrous/semi-ui-react';

标准的进度条

通过stroke属性来控制进度条的填充色
通过percent属性控制已完成的进度
通过size属性控制进度条尺寸
通过aria-label说明进度条具体代表含义
如果size预设的尺寸不满足,可以通过style传入 height 自定义进度条高度






代码
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 展示不确定状态。该属性支持条状和环形进度条;开启后 percent 不再控制进度长度,且不会展示 showInfo 文本。


代码
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>
    );
}

展示百分比文本

通过showInfo控制是否展示百分比数字,可以通过format格式化展示文本

10%

25%

50%

500‰
代码
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>
    );
}

垂直的进度条

设置direction='vertical',展示垂直进度条,可以通过style传入 width 控制进度条宽度

代码
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>
    );
}

环形进度条

将 type 设为circle,进度条将会展示成环状。进度条默认尺寸为 72 x 72

代码
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>
    );
}

你可以通过修改width来控制环形进度条的大小

代码
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>
    );
}

小号的环形进度条

小号进度条默认尺寸为 24 x 24

代码
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>
    );
}

动态改变进度

文字中的数字会以动画过渡到新的 percent。动画进行中再次修改 percent,新动画从当前显示的数字起算。

40%
代码
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>
    );
}
代码
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>
    );
}

自定义中心文字内容

你可以通过传入 format 函数自定义中心文字,format 的入参为当前百分比
如果不需要中心文本内容,你可以将 showInfo 设为 false,或者在 format 中直接返回空字符串

75Days
Done
代码
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>
    );
}

圆角/方角边缘

通过 strokeLinecap 属性,你可以控制环形进度条边缘形状

代码
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>
    );
}

自定义进度条颜色

可通过设置 stroke 属性,自定义具体 percent 的颜色

10%
10%
代码
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}
            />
        </>
    );
}

自动补齐颜色区间

可通过设置 strokeGradient 属性,属性为 true 时自动补齐颜色区间,生成渐变色

0%
0%
65%
代码
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 参考

Props

属性说明类型默认值
className根元素的类名。string""
direction条状进度条的方向,可选 horizontal 或 vertical。'horizontal' | 'vertical'"horizontal"
format格式化函数,入参为当前显示的百分比(截断到 0 到 100,动画过程中为中间值),返回值渲染在环形进度条中心或条状进度条右侧。每次渲染都会调用,即使 showInfo 为 false。Type(percent: number) => React.ReactNodeType(percent: number) => `${percent}%`
indeterminate是否为不确定状态。开启后 percent 不再控制进度长度,不显示文字,且不设置 aria-valuenow。booleanfalse
motion文字中的数字是否以动画过渡到新的 percent;关闭后直接跳到目标值。Motiontrue
orbitStroke进度条轨道的填充色;未设置时由样式决定。string-
percent进度百分比;超出 0 到 100 的值会被截断。number0
ref根元素(role="progressbar")的引用。TypeReact.Ref<HTMLDivElement>-
showInfo是否显示文字:环形显示在中间,条状显示在右侧。size 为 small 的环形进度条不显示文字。booleanfalse
size尺寸,可选 default、small(仅环形生效)或 large(仅条状生效)。Size"default"
stroke填充色。数组形式为 { percent, color } 的区间列表,color 可为任意 CSS 颜色或 Semi 色板名,如 blue、orange-9,未写色阶时取 5。string | StrokeArr-
strokeGradient是否在相邻颜色区间之间生成渐变色补齐颜色,仅在 stroke 为区间数组时生效。booleanfalse
strokeLinecap环形进度条端点形状,可选 round 或 square;条状进度条不生效。'round' | 'square'"round"
strokeWidth环形进度条的线宽。number4
style根元素的样式。React.CSSProperties{}
type类型,可选 line 或 circle。'line' | 'circle'"line"
width环形进度条的直径,仅 type 为 circle 时生效;未设置时,size 为 small 取 24,否则取 72。number-

aria-label、aria-labelledby、aria-valuetext、id 等原生属性展开到根元素(role="progressbar")上。

Accessibility

ARIA

  • Progress 具有 progressbar role 来表示它是一个进度条组件。
  • Progress 会自动将 aria-valuenow 设置为传递给组件的进度百分比(percent),以确保屏幕阅读器可以获取正确的百分比数值。当 indeterminate=true 时,由于当前进度未知,不设置 aria-valuenow。另外,Progress 支持传入 aria-valuetext,当你传入时,根据 W3C 规范,aria-valuetext 将优先被屏幕阅读器使用消费,而不是 aria-valuenow
  • Progress 支持传入 aria-label、aria-labelledby
    • 当 Progress 外部存在关于 Progress 作用的描述元素时,你可以通过 aria-labelledby 显式指定某些元素的 id 是 Progress 的标签
    • 否则你应当通过 aria-label 说明 Progress 所代表的具体数值含义
// 推荐用法
<p id="progressbar-label">Disk Usage</p>
<Progress aria-labelledby="progressbar-label" percent={80} />

// 推荐用法
<Progress aria-label='Percent of disk usage' percent={80} />
<Progress aria-label='Percent of file downloaded' percent={80} />

// 使用 aria-valuetext
<Progress aria-label='Percent of disk usage' percent={80} aria-valuetext="Step 2: Copying files... "/>

文案规范

  • 如果进度条过程复杂,或者有很长的等待时间,可以使用帮助文本来做说明。这样可以让用户知道正在发生的进度进展

设计变量

下表是组件内部的 Sass 变量,不能覆写。定制样式请覆写 --semi-* CSS 变量(见 Design Token 页),或写不分层的 CSS 规则。
Sass 变量值用法
$color-progress_default-bgvar(--semi-color-fill-0)默认背景色
$color-progress_track_inner-bgvar(--semi-color-success)默认进度色
$color-progress_line_text-textvar(--semi-color-text-0)百分比文本文字颜色
$color-progress_circle-textvar(--semi-color-text-0)环形进度百分比文字颜色
$motion-progress-transition_duration0.3s进度条动画时长
$motion-progress-transition_timing_functioncubic-bezier(0.62, 0.05, 0.36, 0.95)进度条动画曲线
$height-progress_horizontal4px水平进度条高度
$height-progress_horizontal_large6px大尺寸水平进度条高度
$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-fontWeight600百分比文本字重
$width-progress_line_text45px百分比文本最小宽度
$width-progress_vertical4px垂直进度条宽度
$width-progress_vertical_large6px大尺寸垂直进度条宽度
$radius-progress_trackvar(--semi-border-radius-small)背景圆角大小
$radius-progress_track_innervar(--semi-border-radius-small)进度条圆角大小