Basic Components
[02] Basic Components
Progress
Progress is a determinate bar for a task with a known size, such as an upload or a setup step. A role="progressbar" track whose fill grows with value.
Progress is a determinate bar: it shows how much of a task with a known size is done, such as a file upload, an import or step 3 of 8 in a setup flow. It renders a role="progressbar" track with aria-valuenow, aria-valuemin and aria-valuemax, and a fill that grows with value. It takes no children, so a label or a percentage goes beside it. When the end of the wait is unknown, use Spinner instead. Progress needs @vaneui/ui 1.4.5 or later.
Basic usage
value is required and fills the bar against max, which is 100 by default. Give the bar an aria-label, since the track itself carries no text.
<Progress value={40} aria-label="Upload"/>md, primary, pill, transition and wFull are defaults, so a bare <Progress value={40}/> is an 8px pill bar across the full width of its parent.
Setting the range with max
Set max when the value counts something other than percent, such as steps or megabytes. value is clamped to the range 0 to max: a value above max shows a full bar and reports max in aria-valuenow, and a negative value shows an empty one.
<Col> <Progress value={3} max={8} aria-label="Setup, step 3 of 8"/> <Progress value={8} max={8} aria-label="Setup, step 8 of 8"/></Col>Sizes
Size sets the bar height: 2, 4, 8, 12 and 16px from xs to xl, with md (8px) as the default. In a Row, flex1 lets the bar take the space its label leaves.
xs
sm
md
lg
xl
<Col> <Row> <Text sm secondary className="w-8">xs</Text> <Progress xs flex1 value={60} aria-label="Progress xs"/> </Row> <Row> <Text sm secondary className="w-8">sm</Text> <Progress sm flex1 value={60} aria-label="Progress sm"/> </Row> <Row> <Text sm secondary className="w-8">md</Text> <Progress flex1 value={60} aria-label="Progress md"/> </Row> <Row> <Text sm secondary className="w-8">lg</Text> <Progress lg flex1 value={60} aria-label="Progress lg"/> </Row> <Row> <Text sm secondary className="w-8">xl</Text> <Progress xl flex1 value={60} aria-label="Progress xl"/> </Row></Col>Appearances
The fill is a filled bar in the appearance color, and the track stays neutral whatever the appearance. With the default primary, the fill is near-black in light mode and near-white in dark mode.
<Col> <Progress value={70} aria-label="Primary"/> <Progress accent value={70} aria-label="Accent"/> <Progress secondary value={70} aria-label="Secondary"/> <Progress tertiary value={70} aria-label="Tertiary"/> <Progress success value={70} aria-label="Success"/> <Progress danger value={70} aria-label="Danger"/> <Progress warning value={70} aria-label="Warning"/> <Progress info value={70} aria-label="Info"/></Col>Shapes
pill is the default. rounded and sharp square the ends off, and the fill follows the shape of the track.
<Col> <Progress lg value={45} aria-label="Pill progress"/> <Progress lg rounded value={45} aria-label="Rounded progress"/> <Progress lg sharp value={45} aria-label="Sharp progress"/></Col>Animating the progress bar to a new value
With the default transition, the fill eases to each new value over --transition-duration (200ms); noTransition makes it jump. Under prefers-reduced-motion the fill moves without the animation. Each click below sends another megabyte, and the bar turns success once the upload completes.
quarterly-report.pdf
2 of 6MB
Uploading to the shared drive
const total = 6;const [sent, setSent] = useState(2);const done = sent >= total;
return ( <Card sm className="max-w-md"> <Row justifyBetween> <Text sm fontSemibold>quarterly-report.pdf</Text> <Text sm secondary>{sent} of {total}MB</Text> </Row> <Progress sm success={done} value={sent} max={total} aria-label="Uploading quarterly-report.pdf"/> <Row justifyBetween> <Text xs secondary>{done ? 'Upload complete' : 'Uploading to the shared drive'}</Text> <Button xs secondary onClick={() => setSent(done ? 0 : sent + 1)}> {done ? 'Restart' : 'Send 1MB'} </Button> </Row> </Card>);Visible labels and value text
When a visible label names the bar, point aria-labelledby at it instead of repeating the text in aria-label. Screen readers announce a progressbar's value as a percentage of the range; for a count, aria-valuetext gives the wording to read instead.
Importing contacts
3 of 8 files
<Col> <Row justifyBetween> <Text sm id="import-label">Importing contacts</Text> <Text sm secondary>3 of 8 files</Text> </Row> <Progress value={3} max={8} aria-labelledby="import-label" aria-valuetext="3 of 8 files"/></Col>Customizing
Progress has two theme nodes for themeDefaults: progress.main for the track and progress.fill for the bar inside it. The fill follows the track's appearance, shape and transition whenever they differ from the library defaults, so most changes go on main. A fill default, such as success below, applies while the track keeps its default appearance.
<ThemeProvider themeDefaults={{ progress: { main: { sm: true }, fill: { success: true } },}}> <Progress value={65} aria-label="Storage used"/></ThemeProvider>Progress Props
| Prop | Category | Default | Description |
|---|---|---|---|
accent | Appearance | Accent color appearance (rose) | |
danger | Appearance | Danger color appearance (red) | |
info | Appearance | Info color appearance (cyan) | |
inheritAppearance | Appearance | Inherit appearance from parent — suppresses own data-appearance/data-variant, uses parent's CSS variables | |
primary | Appearance | ✓ | Primary color appearance (gray) |
secondary | Appearance | Secondary color appearance (gray) | |
success | Appearance | Success color appearance (green) | |
tertiary | Appearance | Tertiary color appearance | |
warning | Appearance | Warning color appearance (amber) | |
flex1 | Flex | Take up remaining space (= | |
flexAuto | Flex | Grow but respect intrinsic size (= | |
flexNone | Flex | Don't grow and don't shrink (= | |
margin | Margin | Enable margin on all sides | |
marginB | Margin | Enable only bottom margin | |
marginT | Margin | Enable only top margin | |
marginX | Margin | Enable only horizontal (inline) margin | |
marginY | Margin | Enable only vertical (block) margin | |
noMargin | Margin | ✓ | Disable margin (reset to 0) |
pill | Shape | ✓ | Fully rounded corners (circular) |
rounded | Shape | Medium rounded corners (default) | |
sharp | Shape | No rounded corners (square) | |
lg | Size | Large size | |
md | Size | ✓ | Medium size (default) |
sm | Size | Small size | |
xl | Size | Extra large size | |
xs | Size | Extra small size |
Layout & utility props (gap, padding, hide, items, justify, ...) — documented on Common Props
| Prop | Category | Default | Description |
|---|---|---|---|
desktopHide | Hide | Hide element on desktop devices and below (max-desktop: 80rem) | |
mobileHide | Hide | Hide element on mobile devices and below (max-mobile: 48rem) | |
tabletHide | Hide | Hide element on tablet devices and below (max-tablet: 64rem) | |
overflowAuto | Overflow | Auto overflow - show scrollbars if needed | |
overflowClip | Overflow | Clip overflow - hard clip without scrollbars | |
overflowHidden | Overflow | ✓ | Hidden overflow - clip content without scrollbars |
overflowScroll | Overflow | Scroll overflow - always show scrollbars | |
overflowVisible | Overflow | Visible overflow - content extends beyond bounds | |
overflowXAuto | Overflow | Auto overflow on X-axis only | |
overflowXClip | Overflow | Clip overflow on X-axis only | |
overflowXHidden | Overflow | Hidden overflow on X-axis only | |
overflowXScroll | Overflow | Scroll overflow on X-axis only | |
overflowXVisible | Overflow | Visible overflow on X-axis only | |
overflowYAuto | Overflow | Auto overflow on Y-axis only | |
overflowYClip | Overflow | Clip overflow on Y-axis only | |
overflowYHidden | Overflow | Hidden overflow on Y-axis only | |
overflowYScroll | Overflow | Scroll overflow on Y-axis only | |
overflowYVisible | Overflow | Visible overflow on Y-axis only | |
noTransition | Transition | Disable transitions for instant state changes | |
transition | Transition | ✓ | Enable smooth transitions between states |
wAuto | Width | Set width to auto | |
wFit | Width | Set width to fit-content | |
wFull | Width | ✓ | Set width to 100% |
wScreen | Width | Set width to 100vw (viewport width), removes max-width constraint |