Progress
The Progress component displays the status of a task or operation over time.
'use client';
import * as React from 'react';
import { useTheme } from '@mui/system';
import * as Progress from '@base_ui/react/Progress';
export default function UnstyledProgressIntroduction() {
  return (
    <div className="App">
      <Progress.Root className="Progress" value={50} aria-labelledby="ProgressLabel">
        <span className="Label" id="ProgressLabel">
          Uploading files
        </span>
        <Progress.Track className="Progress-track">
          <Progress.Indicator className="Progress-indicator" />
        </Progress.Track>
      </Progress.Root>
      <Styles />
    </div>
  );
}
function useIsDarkMode() {
  const theme = useTheme();
  return theme.palette.mode === 'dark';
}
export function Styles() {
  const isDarkMode = useIsDarkMode();
  return (
    <style>{`
      .App {
        font-family: system-ui, sans-serif;
        width: 20rem;
        padding: 1rem;
      }
      .Progress {
        display: flex;
        flex-flow: column nowrap;
        gap: 1rem;
      }
      .Progress-track {
        position: relative;
        width: 100%;
        height: 4px;
        border-radius: 9999px;
        background-color: ${grey[400]};
        display: flex;
        overflow: hidden;
      }
      .Progress-indicator {
        background-color: ${isDarkMode ? BLUE400 : BLUE500};
        border-radius: inherit;
      }
      .Label {
        cursor: unset;
        font-weight: bold;
      }
    `}</style>
  );
}
const grey = {
  50: '#F3F6F9',
  100: '#E5EAF2',
  200: '#DAE2ED',
  300: '#C7D0DD',
  400: '#B0B8C4',
  500: '#9DA8B7',
  600: '#6B7A90',
  700: '#434D5B',
  800: '#303740',
  900: '#1C2025',
};
const BLUE400 = '#3399FF';
const BLUE500 = '#007FFF';
Installation
Base UI components are all available as a single package.
npm install @base_ui/react
Once you have the package installed, import the component.
import * as Progress from '@base_ui/react/Progress';
Anatomy
Progress
- <Progress.Root />is a top-level component that wraps the other components.
- <Progress.Track />renders the rail that represents the total length or duration of progress.
- <Progress.Indicator />renders the filled portion of the track.
<Progress.Root>
  <Progress.Track>
    <Progress.Indicator />
  </Progress.Track>
</Progress.Root>Value
Determinate
The value prop represents the percentage value of the Progress component. The default minimum and maximum values are 0 and 100, and can be changed with the min and max props. When progress is determinate the data-state attribute is initially 'progressing', changing to 'complete' when value equals max.
function App() {
  const [progressValue] = React.useState(25);
  return (
    <Progress.Root value={progressValue} min={0} max={100}>
      <Progress.Track>
        <Progress.Indicator />
      </Progress.Track>
    </Progress.Root>
  );
}Indeterminate
Set value to null to configure an indeterminate progress bar. The data-state attribute will be set to indeterminate.
<Progress.Root value={null}>
  <Progress.Track>
    <Progress.Indicator />
  </Progress.Track>
</Progress.Root>'use client';
import * as React from 'react';
import * as BaseProgress from '@base_ui/react/Progress';
import { Box, styled, keyframes, css } from '@mui/system';
export default function IndeterminateProgress() {
  return (
    <Box sx={{ width: 320, p: 2 }}>
      <Progress value={null} aria-labelledby="ProgressLabel">
        <span className="Progress-label" id="ProgressLabel">
          Uploading files
        </span>
        <ProgressTrack>
          <ProgressIndicator />
        </ProgressTrack>
      </Progress>
    </Box>
  );
}
const Progress = styled(BaseProgress.Root)`
  display: flex;
  flex-flow: column nowrap;
  gap: 1rem;
`;
const ProgressTrack = styled(BaseProgress.Track)(
  ({ theme }) => `
    position: relative;
    width: 100%;
    height: 4px;
    border-radius: 9999px;
    background-color: ${theme.palette.mode === 'dark' ? grey[400] : grey[400]};
    display: flex;
    overflow: hidden;
  `,
);
const indeterminateProgress = keyframes`
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(20rem);
  }
`;
const ProgressIndicator = styled(BaseProgress.Indicator)(
  ({ theme }) => css`
    background-color: ${theme.palette.mode === 'dark' ? BLUE400 : BLUE500};
    border-radius: inherit;
    &[data-state='indeterminate'] {
      width: 25%;
      animation: ${indeterminateProgress} 1.5s infinite ease-in-out;
      will-change: transform;
    }
  `,
);
const grey = {
  50: '#F3F6F9',
  100: '#E5EAF2',
  200: '#DAE2ED',
  300: '#C7D0DD',
  400: '#B0B8C4',
  500: '#9DA8B7',
  600: '#6B7A90',
  700: '#434D5B',
  800: '#303740',
  900: '#1C2025',
};
const BLUE400 = '#3399FF';
const BLUE500 = '#007FFF';
RTL
Set the direction prop to 'rtl' to change the direction that the Indicator fills towards for right-to-left languages:
<Progress.Root direction="rtl">{/* Subcomponents */}</Progress.Root>'use client';
import * as React from 'react';
import * as BaseProgress from '@base_ui/react/Progress';
import { Box, styled } from '@mui/system';
export default function RtlProgress() {
  return (
    <Box sx={{ width: 320, p: 2 }}>
      <Progress value={65} aria-labelledby="RtlProgressLabel" dir="rtl">
        <span className="Progress-label" id="RtlProgressLabel">
          Uploading files (RTL)
        </span>
        <ProgressTrack>
          <ProgressIndicator />
        </ProgressTrack>
      </Progress>
    </Box>
  );
}
const Progress = styled(BaseProgress.Root)`
  display: flex;
  flex-flow: column nowrap;
  gap: 1rem;
`;
const ProgressTrack = styled(BaseProgress.Track)(
  ({ theme }) => `
    position: relative;
    width: 100%;
    height: 4px;
    border-radius: 9999px;
    background-color: ${theme.palette.mode === 'dark' ? grey[400] : grey[400]};
    display: flex;
    overflow: hidden;
  `,
);
const ProgressIndicator = styled(BaseProgress.Indicator)(
  ({ theme }) => `
    background-color: ${theme.palette.mode === 'dark' ? BLUE400 : BLUE500};
    border-radius: inherit;
  `,
);
const grey = {
  50: '#F3F6F9',
  100: '#E5EAF2',
  200: '#DAE2ED',
  300: '#C7D0DD',
  400: '#B0B8C4',
  500: '#9DA8B7',
  600: '#6B7A90',
  700: '#434D5B',
  800: '#303740',
  900: '#1C2025',
};
const BLUE400 = '#3399FF';
const BLUE500 = '#007FFF';
Overriding default components
Use the render prop to override the rendered element for all subcomponents:
<Progress.Indicator render={<MyCustomIndicator />} />
// or
<Progress.Indicator render={(props) => <MyCustomIndicator {...props} />} />Accessibility
The Progress component implements the ARIA progressbar specification.
When using Progress, ensure that it has a human-readable text label by using either the aria-label, aria-labelledby, or getAriaLabel prop:
<Progress.Root aria-labelledby="MyCustomLabel">
  <MyCustomLabel id="MyCustomLabel">Loading progress<MyCustomLabel/>
  <Progress.Track>
    <Progress.Indicator />
  </Progress.Track>
</Progress.Root>
 
// or
 
<Progress.Root aria-label="Loading progress">
  <Progress.Track>
    <Progress.Indicator />
  </Progress.Track>
</Progress.Root>API Reference
ProgressRoot
| Prop | Type | Default | Description | 
|---|---|---|---|
| aria-label | string | The label for the Indicator component. | |
| aria-labelledby | string | An id or space-separated list of ids of elements that label the Indicator component. | |
| aria-valuetext | string | A string value that provides a human-readable text alternative for the current value of the progress indicator. | |
| className | union | Class names applied to the element or a function that returns them based on the component's state. | |
| direction | enum | 'ltr' | The direction that progress bars fill in | 
| getAriaLabel | func | Accepts a function which returns a string value that provides an accessible name for the Indicator component | |
| getAriaValueText | func | Accepts a function which returns a string value that provides a human-readable text alternative for the current value of the progress indicator. | |
| max | number | 100 | The maximum value | 
| min | number | 0 | The minimum value | 
| render | union | A function to customize rendering of the component. | |
| value | number | null | The current value. The component is indeterminate when value is null. | 
ProgressTrack
| Prop | Type | Default | Description | 
|---|---|---|---|
| className | union | Class names applied to the element or a function that returns them based on the component's state. | |
| render | union | A function to customize rendering of the component. | 
ProgressIndicator
| Prop | Type | Default | Description | 
|---|---|---|---|
| className | union | Class names applied to the element or a function that returns them based on the component's state. | |
| render | union | A function to customize rendering of the component. |