Skip to content

Commit

Permalink
fix(pf4): scroll to top on switching to a different step
Browse files Browse the repository at this point in the history
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 <boaz.shuster.github@gmail.com>
  • Loading branch information
boaz0 committed Feb 20, 2020
1 parent 620a52e commit 3851f1c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 26 deletions.
1 change: 1 addition & 0 deletions config/jest.setup.js
Expand Up @@ -2,3 +2,4 @@ import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });
Element.prototype.scrollTo = () => {};
73 changes: 47 additions & 26 deletions packages/pf4-component-mapper/src/form-fields/wizard/wizard-step.js
Expand Up @@ -4,38 +4,59 @@ import { Title } from '@patternfly/react-core/dist/js/components/Title/Title';
import PropTypes from 'prop-types';
import WizardStepButtons from './step-buttons';

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

RenderTitle.propTypes = {
title: PropTypes.node,
customTitle: PropTypes.node,
};

const WizardStep = ({
title,
description,
fields,
formOptions,
showTitles,
showTitle,
customTitle,
...rest
}) => {
return (
<Fragment>
<WizardBody hasBodyPadding={ true }>
<div className="pf-c-form">
{ ((showTitles && showTitle !== false) || showTitle) && <RenderTitle title={ title } customTitle={ customTitle } /> }
{ fields.map(item => formOptions.renderForm([ item ], formOptions)) }
</div>
</WizardBody>
<WizardStepButtons
formOptions={ formOptions }
{ ...rest }
/>
</Fragment>
);
};
class WizardStep extends React.Component {
formRef = React.createRef();
componentDidUpdate(prevProps) {
// we want to scroll to top of the new step so
// the user experience won't suck. For instance,
// when the first step contains many fields that you have to scroll down
// to fill all the data for the next step. If the next step contains instructions
// at the top, the user will miss them because the scrollbar offset will stay at
// the same place it was.
if(prevProps.stepKey !== this.props.stepKey) {
// HACK: I can not pass ref to WizardBody because it is not
// wrapped by forwardRef. However, the step body (the one that overflows)
// is the grand parent of the form element.
const stepBody = this.formRef.current && this.formRef.current.parentNode.parentNode;
stepBody.scrollTo({top: 0, left: 0, behavior: 'smooth'});
}
}

render() {
const {
title,
description,
fields,
formOptions,
showTitles,
showTitle,
customTitle,
...rest
} = this.props;

return (
<Fragment>
<WizardBody hasBodyPadding={true}>
<div ref={this.formRef} className="pf-c-form">
{((showTitles && showTitle !== false) || showTitle) && <RenderTitle title={title} customTitle={customTitle} />}
{fields.map(item => formOptions.renderForm([item], formOptions))}
</div>
</WizardBody>
<WizardStepButtons
formOptions={formOptions}
{...rest}
/>
</Fragment>
);
}
}

WizardStep.propTypes = {
title: PropTypes.node,
Expand Down

0 comments on commit 3851f1c

Please sign in to comment.