Skip to content

Commit e8991b3

Browse files
karolinelienclaude
andcommitted
fix: [DHIS2-21286] scroll first failed field clear of sticky ScopeSelector
Two bugs caused validation-failure scroll to land in the wrong place: 1. withGotoInterface wrapped its class in forwardRef during the React 18 migration (09ed283). The outer ref then pointed at the inner field component, not GotoFieldInterface, so .goto() silently no-op'd on every D2Form section field. Drop the wrapper - no consumer reads the forwarded ref. 2. Both goto() implementations did scrollIntoView() then post-corrected with window.scroll(0, scrolledY - 48). The guard skipped the correction whenever scrolledY === 0 (e.g. OccurredAt near top of doc), leaving the field flush with the viewport top - and behind the sticky ScopeSelector bar. Use scrollIntoView({block:'start'}) + scrollMarginTop:80px on the wrapper so the browser lands the field 80px below the viewport top regardless of position. AI Assisted Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ead5b8d commit e8991b3

2 files changed

Lines changed: 8 additions & 24 deletions

File tree

src/core_modules/capture-core/components/DataEntry/dataEntryField/internal/DataEntryField.component.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ class DataEntryFieldPlain extends React.Component<Props> {
1919

2020
goto() {
2121
if (this.gotoInstance) {
22-
this.gotoInstance.scrollIntoView();
23-
24-
const scrolledY = window.scrollY;
25-
if (scrolledY) {
26-
window.scroll(0, scrolledY - 48);
27-
}
22+
this.gotoInstance.scrollIntoView({ block: 'start' });
2823
}
2924
}
3025

@@ -60,6 +55,7 @@ class DataEntryFieldPlain extends React.Component<Props> {
6055
ref={(gotoInstance) => { this.gotoInstance = gotoInstance; }}
6156
key={propName}
6257
data-test={`dataentry-field-${propName}`}
58+
style={{ scrollMarginTop: '80px' }}
6359
>
6460
<Component
6561
onBlur={this.handleSet}
Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,26 @@
1-
import React, { forwardRef } from 'react';
1+
import * as React from 'react';
22

33
export const withGotoInterface = () =>
4-
(InnerComponent: React.ComponentType<any>) => {
4+
(InnerComponent: React.ComponentType<any>) =>
55
class GotoFieldInterface extends React.Component<any> {
66
gotoInstance: any;
77

88
goto() {
99
if (this.gotoInstance) {
10-
this.gotoInstance.scrollIntoView();
11-
12-
const scrolledY = window.scrollY;
13-
if (scrolledY) {
14-
// TODO: Set the modifier some other way (caused be the fixed header)
15-
window.scroll(0, scrolledY - 48);
16-
}
10+
this.gotoInstance.scrollIntoView({ block: 'start' });
1711
}
1812
}
1913

2014
render() {
21-
const { forwardedRef, ...rest } = this.props;
2215
return (
2316
<div
2417
ref={(gotoInstance) => { this.gotoInstance = gotoInstance; }}
18+
style={{ scrollMarginTop: '80px' }}
2519
>
2620
<InnerComponent
27-
ref={forwardedRef}
28-
{...rest}
21+
{...this.props}
2922
/>
3023
</div>
3124
);
3225
}
33-
}
34-
35-
return forwardRef<any, any>((props, ref) => (
36-
<GotoFieldInterface {...props} forwardedRef={ref} />
37-
));
38-
};
26+
};

0 commit comments

Comments
 (0)