ProgressBar 进度条
进度条用于展示某项操作随时间变化的确定或不确定进度。
用法
import { ProgressBar, Label } from '@lenso/ui';此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ progress: { width: 256 } });
export function Basic() { return ( <ProgressBar aria-label="Loading" xstyle={styles.progress} value={60}> <ProgressBar.Label>Loading</ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
组件结构
import { ProgressBar, Label } from '@lenso/ui';
export default () => ( <ProgressBar value={60}> <Label>Loading</Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar>);示例
尺寸
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ column: { display: "flex", width: 256, flexDirection: "column", gap: 24 },});export function Sizes() { return ( <div {...stylex.props(styles.column)}> <ProgressBar aria-label="Small" size="sm" value={40}> <ProgressBar.Label>Small</ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> <ProgressBar aria-label="Medium" size="md" value={60}> <ProgressBar.Label>Medium</ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> <ProgressBar aria-label="Large" size="lg" value={80}> <ProgressBar.Label>Large</ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> </div> );}export default Sizes;Local adaptation source above. Derived from HeroUI v3.2.6 source.
颜色
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ column: { display: "flex", width: 256, flexDirection: "column", gap: 24 },});export function Colors() { return ( <div {...stylex.props(styles.column)}> {(["default", "accent", "success", "warning", "danger"] as const).map((color) => ( <ProgressBar key={color} color={color} value={50}> <ProgressBar.Label> {color[0]?.toUpperCase()} {color.slice(1)} </ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> ))} </div> );}export default Colors;Local adaptation source above. Derived from HeroUI v3.2.6 source.
无可见标签
无需可见标签时,使用 aria-label 提供无障碍标签。
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ progress: { width: 256 } });export function WithoutLabel() { return ( <ProgressBar aria-label="Loading progress" xstyle={styles.progress} value={45}> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> );}export default WithoutLabel;Local adaptation source above. Derived from HeroUI v3.2.6 source.
不确定进度
无法确定进度时使用 isIndeterminate。
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0); null is Base UI's indeterminate value.import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ progress: { width: 256 } });export function Indeterminate() { return ( <ProgressBar aria-label="Loading" xstyle={styles.progress} value={null}> <ProgressBar.Label>Loading...</ProgressBar.Label> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> );}export default Indeterminate;Local adaptation source above. Derived from HeroUI v3.2.6 source.
自定义数值范围
使用 minValue、maxValue 与 formatOptions 自定义取值范围与显示格式。
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0); native Base UI range and selection contracts.import { NumberField, ProgressBar, Select, Separator } from "@lenso/ui";import { useId, useState } from "react";import * as stylex from "@stylexjs/stylex";const formatStyleOptions = [ { label: "Currency", value: "currency" }, { label: "Percent", value: "percent" }, { label: "Decimal", value: "decimal" }, { label: "Unit", value: "unit" },];const formatOptionsMap: Record<string, Intl.NumberFormatOptions> = { currency: { currency: "USD", style: "currency" }, decimal: { style: "decimal" }, percent: { style: "percent" }, unit: { style: "unit", unit: "mile" },};const styles = stylex.create({ root: { display: "flex", width: "100%", flexDirection: { default: "column", "@media (min-width: 768px)": "row" }, alignItems: { default: "stretch", "@media (min-width: 768px)": "center" }, gap: { default: 24, "@media (min-width: 768px)": 40 }, }, preview: { display: "flex", width: "100%", maxWidth: 448, flex: 1, justifyContent: "center" }, progress: { width: "100%", maxWidth: 208 }, horizontal: { display: { default: "block", "@media (min-width: 768px)": "none" } }, vertical: { display: { default: "none", "@media (min-width: 768px)": "block" } }, options: { display: "flex", maxWidth: 208, flexDirection: "column", gap: 12 }, caption: { fontSize: 12, lineHeight: "16px", fontWeight: 500, color: "var(--muted)" }, field: { display: "flex", flexDirection: "column", gap: 4 }, label: { fontSize: 14, lineHeight: "20px", fontWeight: 500 },});export function CustomValue() { const valueId = useId(); const minId = useId(); const maxId = useId(); const [value, setValue] = useState(750); const [minValue, setMinValue] = useState(0); const [maxValue, setMaxValue] = useState(1000); const [format, setFormat] = useState("percent"); return ( <div {...stylex.props(styles.root)}> <div {...stylex.props(styles.preview)}> <ProgressBar aria-label="Revenue" xstyle={styles.progress} format={formatOptionsMap[format]} max={maxValue} min={minValue} value={value} > <ProgressBar.Label>Progress</ProgressBar.Label> <ProgressBar.Output /> <ProgressBar.Track> <ProgressBar.Fill /> </ProgressBar.Track> </ProgressBar> </div> <Separator xstyle={styles.horizontal} /> <Separator xstyle={styles.vertical} orientation="vertical" /> <div {...stylex.props(styles.options)}> <p {...stylex.props(styles.caption)}>Options</p> <NumberField id={valueId} min={minValue} max={maxValue} value={value} variant="secondary" onValueChange={(next) => { if (next !== null) setValue(next); }} > <label htmlFor={valueId} {...stylex.props(styles.label)}> Value </label> <NumberField.Group> <NumberField.DecrementButton /> <NumberField.Input /> <NumberField.IncrementButton /> </NumberField.Group> </NumberField> <NumberField id={minId} min={0} max={maxValue - 1} value={minValue} variant="secondary" onValueChange={(next) => { if (next === null) return; setMinValue(next); setValue((current) => Math.max(next, current)); }} > <label htmlFor={minId} {...stylex.props(styles.label)}> Min Value </label> <NumberField.Group> <NumberField.DecrementButton /> <NumberField.Input /> <NumberField.IncrementButton /> </NumberField.Group> </NumberField> <NumberField id={maxId} min={minValue + 1} max={2000} value={maxValue} variant="secondary" onValueChange={(next) => { if (next === null) return; setMaxValue(next); setValue((current) => Math.min(next, current)); }} > <label htmlFor={maxId} {...stylex.props(styles.label)}> Max Value </label> <NumberField.Group> <NumberField.DecrementButton /> <NumberField.Input /> <NumberField.IncrementButton /> </NumberField.Group> </NumberField> <div {...stylex.props(styles.field)}> <Select variant="secondary" value={format} items={formatStyleOptions} onValueChange={(next) => { if (next !== null) setFormat(next); }} > <Select.Label>Format</Select.Label> <Select.Trigger> <Select.Value /> <Select.Indicator /> </Select.Trigger> <Select.Portal> <Select.Positioner> <Select.Popover> <Select.List> {formatStyleOptions.map((option) => ( <Select.Item key={option.value} value={option.value}> <Select.ItemText>{option.label}</Select.ItemText> <Select.ItemIndicator /> </Select.Item> ))} </Select.List> </Select.Popover> </Select.Positioner> </Select.Portal> </Select> </div> </div> </div> );}export default CustomValue;Local adaptation source above. Derived from HeroUI v3.2.6 source.
自定义样式
Tailwind CSS
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressBar } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ progress: { width: 256 }, label: { fontWeight: 500, color: "var(--foreground)" }, output: { fontSize: 12, lineHeight: "16px", color: "var(--muted)", fontVariantNumeric: "tabular-nums", }, track: { borderRadius: 9999, backgroundColor: "var(--default)" }, fill: { borderRadius: 9999, backgroundColor: "var(--accent)" },});export function CustomStyles() { return ( <ProgressBar aria-label="Upload progress" xstyle={styles.progress} value={45}> <ProgressBar.Label xstyle={styles.label}>Uploading resume.pdf</ProgressBar.Label> <ProgressBar.Output xstyle={styles.output} /> <ProgressBar.Track xstyle={styles.track}> <ProgressBar.Fill xstyle={styles.fill} /> </ProgressBar.Track> </ProgressBar> );}export default CustomStyles;Local adaptation source above. Derived from HeroUI v3.2.6 source.
全局 CSS
若要自定义组件类,可使用 @layer components 指令。了解更多。
@layer components { .progress-bar { @apply w-full gap-2; }
.progress-bar__track { @apply h-3 rounded-full; }
.progress-bar__fill { @apply rounded-full; }}样式参考
HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
CSS 类
ProgressBar 使用以下 CSS 类(查看源码样式):
基础与元素类 [!toc]
.progress-bar- 基础容器(网格布局).progress-bar__output- 数值文本展示.progress-bar__track- 轨道背景.progress-bar__fill- 轨道上已填充部分
尺寸类 [!toc]
.progress-bar--sm- 小尺寸变体(更细的轨道).progress-bar--md- 中等尺寸变体(默认).progress-bar--lg- 大尺寸变体(更粗的轨道)
颜色类 [!toc]
.progress-bar--default- 默认颜色变体.progress-bar--accent- 强调色变体.progress-bar--success- 成功色变体.progress-bar--warning- 警告色变体.progress-bar--danger- 危险色变体
API 参考
ProgressBar
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
value | number | 0 | 当前值 |
minValue | number | 0 | 最小值 |
maxValue | number | 100 | 最大值 |
isIndeterminate | boolean | false | 是否为不确定进度 |
size | "sm" | "md" | "lg" | "md" | 进度轨道尺寸 |
color | "default" | "accent" | "success" | "warning" | "danger" | "accent" | 填充条颜色 |
formatOptions | Intl.NumberFormatOptions | {style: 'percent'} | 数值展示的数字格式 |
valueLabel | ReactNode | - | 自定义数值标签内容 |
children | ReactNode | (values: ProgressBarRenderProps) => ReactNode | - | 内容或渲染 prop |
ProgressBarRenderProps
使用渲染 prop 模式时,会提供以下值:
| Prop | 类型 | 描述 |
|---|---|---|
percentage | number | 进度百分比(0–100) |
valueText | string | 格式化后的数值文本 |
isIndeterminate | boolean | 是否为不确定进度 |