---
title: Progress Indicators
product: Form Library
description: Learn how to add progress indicators to your survey or form to show users how far along they are in the form or survey completion process, or use the indicators as jump links for easier navigation to a specific section of a form. View a free demo for JavaScript to learn more.
framework: React
source: https://surveyjs.io/form-library/examples/configure-form-navigation-with-progress-indicators/reactjs
index: https://surveyjs.io/form-library/examples/overview.md
---

# Progress Indicators (React)

A progress indicator, or progress bar, is a graphical element that visualizes the status of a particular task or process. Progress indicators provide visual cues that help respondents understand how far along they have advanced in your survey. SurveyJS Form Library ships with a progress bar that can show different types of progress information or allow users to switch survey pages.

## Display and Position the Progress Bar

To display the progress bar, enable the [`showProgressBar`](/form-library/documentation/api-reference/survey-data-model#showProgressBar) property. Use the [`progressBarLocation`](/form-library/documentation/api-reference/survey-data-model#progressBarLocation) property to position the progress bar within your survey. This property accepts the following values:

- `"aboveHeader"` - Displays the progress bar above the survey header.
- `"belowHeader"` - Displays the progress bar below the survey header. In this mode, the progress bar stays on top when users scroll the survey.
- `"bottom"` - Displays the progress bar below survey content.
- `"topBottom"` - Displays the progress bar above and below survey content.
- `"auto"` (default) - Automatically selects between `"aboveHeader"` and `"belowHeader"`.

In this demo, you can use the **Progress bar location** drop-down menu to switch between the positions.

## Specify Progress Information Type

You can also specify the information the progress bar displays: the number of completed pages, answered questions, answered required questions, or correct answers. To do this, set the [`progressBarType`](/form-library/documentation/api-reference/survey-data-model#progressBarType) property to one of the following values:

- `"pages"` (default)       
Indicates the number of completed pages and serves as a navigation element that respondents can use to jump between pages. You can also enable the [`progressBarShowPageNumbers`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#progressBarShowPageNumbers) and [`progressBarShowNavigationText`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#progressBarShowNavigationText) properties if you want to display page numbers, titles, and descriptions in the progress bar. Use a page's [`navigationTitle`](/form-library/documentation/api-reference/page-model#navigationTitle) and [`navigationDescription`](/form-library/documentation/api-reference/page-model#navigationDescription) properties to specify its title and description.
- `"questions"`     
Indicates The number of answered questions.
- `"requiredQuestions"`         
Indicates the number of answered [required questions](https://surveyjs.io/form-library/documentation/api-reference/question#isRequired).
- `"correctQuestions"`          
Indicates the number of correct questions in a [quiz](https://surveyjs.io/form-library/documentation/design-survey/create-a-quiz).

This demo allows you to switch between the `"pages"` and `"questions"` progress bar types at runtime using the **Progress bar type** drop-down menu.

## Files

### `public/index.html`

```html
<div id="surveyElement" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; min-height: 100%; height:100%"></div>
```

### `src/SurveyComponent.jsx`

```js
import React from "react";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";
import "survey-core/survey-core.min.css";
import { themeJson } from "./theme";
import "./index.css";
import { json } from "./json";

function SurveyComponent() {
    const survey = new Model(json);
    survey.applyTheme(themeJson);
    survey.onComplete.add((sender, options) => {
        console.log(JSON.stringify(sender.data, null, 3));
    });
    return (<Survey model={survey} />);
}

export default SurveyComponent;
```

### `src/index.css`

```css
/* You can add your custom CSS here. */
```

### `src/index.js`

```js
import React from "react";
import { createRoot } from "react-dom/client";
import SurveyComponent from "./SurveyComponent";

const root = createRoot(document.getElementById("surveyElement"));
root.render(<SurveyComponent />);
```

### `src/json.js`

```js
export const json = {
  "showProgressBar": true,
  "progressBarLocation": "auto",
  "progressBarType": "pages",
  "progressBarShowPageNumbers": true,
  "progressBarShowNavigationText": true,
  "title": "Customer Satisfaction Survey",
  "pages": [{
    "navigationTitle": "Overall satisfaction",
    "elements": [{
      "type": "matrix",
      "name": "qualities",
      "title": "Please indicate if you agree or disagree with the following statements",
      "columns": [{
        "value": 5,
        "text": "Strongly agree"
      }, {
        "value": 4,
        "text": "Agree"
      }, {
        "value": 3,
        "text": "Neutral"
      }, {
        "value": 2,
        "text": "Disagree"
      }, {
        "value": 1,
        "text": "Strongly disagree"
      }],
      "rows": [{
        "value": "affordable",
        "text": "Product is affordable"
      }, {
        "value": "does-what-it-claims",
        "text": "Product does what it claims"
      }, {
        "value": "better-than-others",
        "text": "Product is better than other products on the market"
      },{
        "value": "easy-to-use",
        "text": "Product is easy to use"
      }]
    }, {
      "type": "rating",
      "name": "satisfaction-score",
      "title": "How satisfied are you with our product?",
      "minRateDescription": "Not satisfied",
      "maxRateDescription": "Completely satisfied"
    }, {
      "type": "rating",
      "name": "recommend",
      "visibleIf": "{satisfaction-score} > 3",
      "title": "How likely are you to recommend our product to a friend or co-worker?",
      "minRateDescription": "Will not recommend",
      "maxRateDescription": "I will recommend"
    }, {
      "type": "comment",
      "name": "suggestions",
      "title": "What would make you more satisfied with our product?"
    }]
  }, {
    "navigationTitle": "Pricing",
    "elements": [{
      "type": "radiogroup",
      "name": "price-comparison",
      "title": "Compared to our competitors, do you feel our product is:",
      "choices": [
        "Less expensive",
        "Priced about the same",
        "More expensive",
        "Not sure"
      ]
    }, {
      "type": "radiogroup",
      "name": "current-price",
      "title": "Do you feel our current price is merited by our product?",
      "choices": [
        "correct|Yes, the price is about right",
        "low|No, the price is too low for your product",
        "high|No, the price is too high for your product"
      ]
    }, {
      "type": "multipletext",
      "name": "price-limits",
      "title": "What is the highest and lowest price you would pay for a product like ours?",
      "items": [{
        "name": "highest",
        "title": "Highest"
      }, {
        "name": "lowest",
        "title": "Lowest"
      }]
    }]
  }, {
    "navigationTitle": "Contacts",
    "elements": [{
      "type": "text",
      "name": "email",
      "title": "Please leave your email address if you would like us to contact you."
    }]
  }]
};
```

### `src/theme.js`

```js
export const themeJson = {
  "themeName": "default",
  "colorPalette": "light",
  "isPanelless": false,
  "backgroundImage": "",
  "backgroundOpacity": 1,
  "backgroundImageAttachment": "scroll",
  "backgroundImageFit": "cover",
  "cssVariables": {
    "--sjs2-color-bg-basic-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-utility-property-grid": "rgba(255, 255, 255, 1)",
    "--sjs2-color-utility-tabs": "rgba(255, 255, 255, 1)",
    "--sjs2-color-utility-toolbox": "rgba(255, 255, 255, 1)",
    "--sjs2-color-bg-basic-primary-dim": "rgba(248, 248, 248, 1)",
    "--sjs2-color-bg-neutral-tertiary-dim": "rgba(243, 243, 243, 1)",
    "--sjs2-color-utility-surface-survey-panelless": "rgba(243, 243, 243, 1)",
    "--sjs2-color-utility-surface-survey": "rgba(243, 243, 243, 1)",
    "--sjs2-color-bg-basic-secondary": "rgba(249, 249, 249, 1)",
    "--sjs2-color-bg-basic-secondary-dim": "rgba(243, 243, 243, 1)",
    "--sjs2-color-fg-basic-primary": "rgba(0, 0, 0, 0.91)",
    "--sjs2-color-fg-basic-secondary": "rgba(0, 0, 0, 0.45)",
    "--sjs2-color-project-brand-600": "rgba(25, 179, 148, 1)",
    "--sjs2-color-bg-brand-secondary": "rgba(25, 179, 148, 0.1)",
    "--sjs2-color-bg-brand-primary-dim": "rgba(20, 164, 139, 1)",
    "--sjs2-color-fg-brand-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-fg-brand-primary-disabled": "rgba(255, 255, 255, 0.25)",
    "--sjs2-base-unit-size": "8px",
    "--sjs2-base-unit-spacing": "8px",
    "--sjs2-base-unit-radius": "4px",
    "--sjs2-color-bg-accent-primary": "rgba(255, 152, 20, 1)",
    "--sjs2-color-bg-accent-secondary": "rgba(255, 152, 20, 0.1)",
    "--sjs2-color-bg-accent-secondary-dim": "rgba(255, 152, 20, 0.25)",
    "--sjs2-color-fg-accent-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-fg-accent-primary-disabled": "rgba(255, 255, 255, 0.25)",
    "--sjs2-border-effect-surface-default": "0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
    "--sjs2-border-effect-floating-default": "0px 2px 6px 0px rgba(0, 0, 0, 0.1),0px 8px 16px 0px rgba(0, 0, 0, 0.1)",
    "--sjs2-border-effect-component-formbox-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
    "--sjs2-border-effect-component-check-true-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
    "--sjs2-border-effect-component-check-false-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
    "--sjs2-color-border-basic-secondary": "rgba(0, 0, 0, 0.09)",
    "--sjs2-color-component-input-default-line": "rgba(0, 0, 0, 0.16)",
    "--sjs2-color-border-basic-secondary-overlay": "rgba(0, 0, 0, 0.16)",
    "--sjs2-color-bg-alert-primary": "rgba(229, 10, 62, 1)",
    "--sjs2-color-bg-alert-secondary": "rgba(229, 10, 62, 0.1)",
    "--sjs2-color-fg-alert-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-bg-positive-primary": "rgba(25, 179, 148, 1)",
    "--sjs2-color-bg-positive-secondary": "rgba(25, 179, 148, 0.1)",
    "--sjs2-color-fg-positive-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-bg-note-primary": "rgba(67, 127, 217, 1)",
    "--sjs2-color-bg-note-secondary": "rgba(67, 127, 217, 0.1)",
    "--sjs2-color-fg-note-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-bg-warning-primary": "rgba(255, 152, 20, 1)",
    "--sjs2-color-bg-warning-secondary": "rgba(255, 152, 20, 0.1)",
    "--sjs2-color-fg-warning-on-primary": "rgba(255, 255, 255, 1)",
    "--sjs2-color-component-header-default-bg": "transparent",
    "--sjs2-typography-font-weight-component-header-title": "700",
    "--sjs2-typography-font-size-component-header-description": "20px",
    "--sjs2-typography-font-weight-component-page-title": "700"
  },
  "header": {
    "height": 50,
    "titlePositionX": "center",
    "titlePositionY": "middle"
  },
  "headerView": "advanced"
};
```

### `package.json`

```json
{
  "dependencies": {
    "react": "latest",
    "react-dom": "latest",
    "survey-core": "latest",
    "survey-react-ui": "latest"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/form-library/examples/configure-form-navigation-with-progress-indicators/angular.md)
- [Vue 3](https://surveyjs.io/form-library/examples/configure-form-navigation-with-progress-indicators/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/configure-form-navigation-with-progress-indicators/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/configure-form-navigation-with-progress-indicators/vanillajs.md)
