+
+
+
+
+ {isApplicable && canNavigateTo ? (
+
+
+
+ ) : (
+
+ {fixedText || text}
+
+ )}
+
+
+ );
+};
+
+ProgressIndicatorItem.propTypes = {
+ text: PropTypes.string.isRequired,
+ href: PropTypes.string,
+ isActive: PropTypes.bool,
+ isCompleted: PropTypes.bool,
+ canNavigateTo: PropTypes.bool,
+ isApplicable: PropTypes.bool,
+ fixedText: PropTypes.oneOf(Object.values(STEP_LABELS)),
+};
+
+export default ProgressIndicatorItem;
diff --git a/src/components/ProgressIndicatorNew/ProgressIndicatorItem.stories.js b/src/components/ProgressIndicatorNew/ProgressIndicatorItem.stories.js
new file mode 100644
index 000000000..a4e89fa87
--- /dev/null
+++ b/src/components/ProgressIndicatorNew/ProgressIndicatorItem.stories.js
@@ -0,0 +1,20 @@
+import {withRouter} from 'storybook-addon-react-router-v6';
+
+import ProgressIndicatorItem from './ProgressIndicatorItem';
+
+export default {
+ title: 'Private API / ProgressIndicatorNew / ProgressIndicatorItem',
+ component: ProgressIndicatorItem,
+ decorators: [withRouter],
+ args: {
+ text: 'Stap 1',
+ href: '#',
+ isActive: false,
+ isCompleted: true,
+ canNavigateTo: false,
+ isApplicable: true,
+ fixedText: null,
+ },
+};
+
+export const Default = {};
diff --git a/src/components/ProgressIndicatorNew/ProgressIndicatorNew.stories.js b/src/components/ProgressIndicatorNew/ProgressIndicatorNew.stories.js
new file mode 100644
index 000000000..aa1afd223
--- /dev/null
+++ b/src/components/ProgressIndicatorNew/ProgressIndicatorNew.stories.js
@@ -0,0 +1,70 @@
+import {withRouter} from 'storybook-addon-react-router-v6';
+
+import {STEP_LABELS} from 'components/constants';
+
+import ProgressIndicatorNew from '.';
+
+export default {
+ title: 'Private API / ProgressIndicatorNew',
+ component: ProgressIndicatorNew,
+ decorators: [withRouter],
+ args: {
+ progressIndicatorTitle: 'Progress',
+ formTitle: 'Formulier',
+ steps: [
+ {
+ slug: 'start-page',
+ to: 'start-page',
+ formDefinition: 'Start page',
+ isCompleted: true,
+ isApplicable: true,
+ isCurrent: false,
+ canNavigateTo: true,
+ fixedText: STEP_LABELS.login,
+ },
+ {
+ uuid: 'd6cab0dd',
+ slug: 'first-step',
+ to: 'first-step',
+ formDefinition: 'Stap 1',
+ isCompleted: true,
+ isApplicable: true,
+ isCurrent: false,
+ canNavigateTo: true,
+ },
+ {
+ uuid: '8e62d7cf',
+ slug: 'second-step',
+ to: 'second-step',
+ formDefinition: 'Stap 2',
+ isCompleted: false,
+ isApplicable: true,
+ isCurrent: true,
+ canNavigateTo: true,
+ },
+ {
+ slug: 'confirmation-page',
+ to: 'confirmation-page',
+ formDefinition: 'Confirmation',
+ isCompleted: false,
+ isApplicable: false,
+ isCurrent: false,
+ canNavigateTo: true,
+ fixedText: STEP_LABELS.confirmation,
+ },
+ {
+ slug: 'summary-page',
+ to: 'summary-page',
+ formDefinition: 'Summary',
+ isCompleted: false,
+ isApplicable: false,
+ isCurrent: false,
+ canNavigateTo: true,
+ fixedText: STEP_LABELS.overview,
+ },
+ ],
+ activeStepTitle: 'Stap 2',
+ },
+};
+
+export const Default = {};
diff --git a/src/components/ProgressIndicatorNew/index.js b/src/components/ProgressIndicatorNew/index.js
new file mode 100644
index 000000000..60879ef07
--- /dev/null
+++ b/src/components/ProgressIndicatorNew/index.js
@@ -0,0 +1,102 @@
+import PropTypes from 'prop-types';
+import React, {useEffect, useState} from 'react';
+import {FormattedMessage, useIntl} from 'react-intl';
+import {useLocation} from 'react-router-dom';
+
+import Caption from 'components/Caption';
+import Card from 'components/Card';
+import List from 'components/List';
+import {STEP_LABELS} from 'components/constants';
+
+import MobileButton from './MobileButton';
+import ProgressIndicatorItem from './ProgressIndicatorItem';
+
+const ProgressIndicatorNew = ({progressIndicatorTitle, formTitle, steps, activeStepTitle}) => {
+ const intl = useIntl();
+ const {pathname: currentPathname} = useLocation();
+ const [expanded, setExpanded] = useState(false);
+
+ const ariaIconLabel = intl.formatMessage({
+ description: 'Progress step indicator toggle icon (mobile)',
+ defaultMessage: 'Toggle the progress status display',
+ });
+
+ const accessibleToggleStepsLabel = intl.formatMessage(
+ {
+ description: 'Active step accessible label in mobile progress indicator',
+ defaultMessage: 'Current step in form {formTitle}: {activeStepTitle}',
+ },
+ {formTitle, activeStepTitle}
+ );
+
+ const modifiers = [];
+ if (!expanded) {
+ modifiers.push('mobile-collapsed');
+ }
+
+ // collapse the expanded progress indicator if nav occurred, see
+ // open-formulieren/open-forms#2673. It's important that *only* the pathname triggers
+ // the effect, which is why exhaustive deps is ignored.
+ useEffect(() => {
+ if (expanded) {
+ setExpanded(false);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [currentPathname]);
+
+ return (
+