Skip to content

Commit d648053

Browse files
authored
feat(protocol-designer): scroll to top of protocol steps if error (#19137)
This PR introduces auto scrolling to the top of the `ProtocolSteps` container if the user selects a new step and timeline errors are present and visible. It also changes the layout of the `ProtocolSteps` `ExportButton` such that it is fixed to the top right of the container. Closes RQA-4488
1 parent f9da61e commit d648053

File tree

1 file changed

+35
-8
lines changed
  • protocol-designer/src/pages/Designer/ProtocolSteps

1 file changed

+35
-8
lines changed

protocol-designer/src/pages/Designer/ProtocolSteps/index.tsx

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useMemo, useState } from 'react'
1+
import { useEffect, useMemo, useRef, useState } from 'react'
22
import { useTranslation } from 'react-i18next'
33
import { useDispatch, useSelector } from 'react-redux'
44
import round from 'lodash/round'
@@ -13,6 +13,7 @@ import {
1313
JUSTIFY_END,
1414
JUSTIFY_SPACE_BETWEEN,
1515
OVERFLOW_AUTO,
16+
POSITION_ABSOLUTE,
1617
POSITION_RELATIVE,
1718
SPACING,
1819
StyledText,
@@ -169,6 +170,23 @@ export function ProtocolSteps({
169170
activeItem?.id !== HARDWARE_ID
170171
const stepDetails = currentStep?.stepDetails ?? null
171172

173+
const stepComponentRef = useRef<HTMLDivElement>(null)
174+
175+
const handleScrollToTop = (): void => {
176+
if (stepComponentRef.current && hasTimelineErrors) {
177+
stepComponentRef.current.scrollIntoView({
178+
behavior: 'smooth',
179+
block: 'start',
180+
})
181+
}
182+
}
183+
184+
useEffect(() => {
185+
if (selectedStepId != null) {
186+
handleScrollToTop()
187+
}
188+
}, [selectedStepId])
189+
172190
let header: string = t(activeItem?.id)
173191
if (currentStep != null) {
174192
header = i18n.format(currentStep.stepName, 'titleCase')
@@ -251,7 +269,12 @@ export function ProtocolSteps({
251269
{isZoomedIn ||
252270
formData != null ||
253271
selectedSubstep != null ? null : (
254-
<Flex justifyContent={JUSTIFY_END}>
272+
<Flex
273+
justifyContent={JUSTIFY_END}
274+
position={POSITION_ABSOLUTE}
275+
right="0"
276+
zIndex={1000}
277+
>
255278
<ExportButton onClick={handleExporting} />
256279
</Flex>
257280
)}
@@ -274,12 +297,16 @@ export function ProtocolSteps({
274297
{isZoomedIn || selectedTerminalItemId === HARDWARE_ID ? null : (
275298
<>
276299
{showTimelineAlerts ? (
277-
<TimelineAlerts
278-
justifyContent={JUSTIFY_CENTER}
279-
width="100%"
280-
flexDirection={DIRECTION_COLUMN}
281-
gridGap={SPACING.spacing4}
282-
/>
300+
<>
301+
{/* empty div to scroll to top of timeline alerts */}
302+
<div ref={stepComponentRef} />
303+
<TimelineAlerts
304+
justifyContent={JUSTIFY_CENTER}
305+
width="100%"
306+
flexDirection={DIRECTION_COLUMN}
307+
gridGap={SPACING.spacing4}
308+
/>
309+
</>
283310
) : null}
284311
<Flex
285312
justifyContent={JUSTIFY_SPACE_BETWEEN}

0 commit comments

Comments
 (0)