Skip to content

Commit 3851f1c

Browse files
committed
fix(pf4): scroll to top on switching to a different step
For instance, when there are two step that are too long for the wizard container (e.g. too many fields) and are next to each other. If you scroll down in one of them and switch to the other, the location of your scroll bar won't reset to the top but will stay at the bottom. This is bad because the user expects the scroll bar to go back to the top of the next step. Signed-off-by: Boaz Shuster <[email protected]>
1 parent 620a52e commit 3851f1c

File tree

2 files changed

+48
-26
lines changed

2 files changed

+48
-26
lines changed

config/jest.setup.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ import { configure } from 'enzyme';
22
import Adapter from 'enzyme-adapter-react-16';
33

44
configure({ adapter: new Adapter() });
5+
Element.prototype.scrollTo = () => {};

packages/pf4-component-mapper/src/form-fields/wizard/wizard-step.js

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,59 @@ import { Title } from '@patternfly/react-core/dist/js/components/Title/Title';
44
import PropTypes from 'prop-types';
55
import WizardStepButtons from './step-buttons';
66

7-
export const RenderTitle = ({ title, customTitle }) => customTitle ? customTitle : <Title headingLevel="h1" size="xl">{ title }</Title>;
7+
export const RenderTitle = ({ title, customTitle }) => customTitle ? customTitle : <Title headingLevel="h1" size="xl">{title}</Title>;
88

99
RenderTitle.propTypes = {
1010
title: PropTypes.node,
1111
customTitle: PropTypes.node,
1212
};
1313

14-
const WizardStep = ({
15-
title,
16-
description,
17-
fields,
18-
formOptions,
19-
showTitles,
20-
showTitle,
21-
customTitle,
22-
...rest
23-
}) => {
24-
return (
25-
<Fragment>
26-
<WizardBody hasBodyPadding={ true }>
27-
<div className="pf-c-form">
28-
{ ((showTitles && showTitle !== false) || showTitle) && <RenderTitle title={ title } customTitle={ customTitle } /> }
29-
{ fields.map(item => formOptions.renderForm([ item ], formOptions)) }
30-
</div>
31-
</WizardBody>
32-
<WizardStepButtons
33-
formOptions={ formOptions }
34-
{ ...rest }
35-
/>
36-
</Fragment>
37-
);
38-
};
14+
class WizardStep extends React.Component {
15+
formRef = React.createRef();
16+
componentDidUpdate(prevProps) {
17+
// we want to scroll to top of the new step so
18+
// the user experience won't suck. For instance,
19+
// when the first step contains many fields that you have to scroll down
20+
// to fill all the data for the next step. If the next step contains instructions
21+
// at the top, the user will miss them because the scrollbar offset will stay at
22+
// the same place it was.
23+
if(prevProps.stepKey !== this.props.stepKey) {
24+
// HACK: I can not pass ref to WizardBody because it is not
25+
// wrapped by forwardRef. However, the step body (the one that overflows)
26+
// is the grand parent of the form element.
27+
const stepBody = this.formRef.current && this.formRef.current.parentNode.parentNode;
28+
stepBody.scrollTo({top: 0, left: 0, behavior: 'smooth'});
29+
}
30+
}
31+
32+
render() {
33+
const {
34+
title,
35+
description,
36+
fields,
37+
formOptions,
38+
showTitles,
39+
showTitle,
40+
customTitle,
41+
...rest
42+
} = this.props;
43+
44+
return (
45+
<Fragment>
46+
<WizardBody hasBodyPadding={true}>
47+
<div ref={this.formRef} className="pf-c-form">
48+
{((showTitles && showTitle !== false) || showTitle) && <RenderTitle title={title} customTitle={customTitle} />}
49+
{fields.map(item => formOptions.renderForm([item], formOptions))}
50+
</div>
51+
</WizardBody>
52+
<WizardStepButtons
53+
formOptions={formOptions}
54+
{...rest}
55+
/>
56+
</Fragment>
57+
);
58+
}
59+
}
3960

4061
WizardStep.propTypes = {
4162
title: PropTypes.node,

0 commit comments

Comments
 (0)