1
+ import { useEffect , useMemo } from 'react'
1
2
import { useTranslation } from 'react-i18next'
2
3
import { useDispatch , useSelector } from 'react-redux'
4
+ import debounce from 'lodash/debounce'
3
5
4
6
import { useConditionalConfirm } from '@opentrons/components'
5
7
@@ -40,10 +42,7 @@ import type { Dispatch, MouseEvent, SetStateAction } from 'react'
40
42
import type { DeleteModalType } from '../../../../components/organisms'
41
43
import type { StepIdType } from '../../../../form-types'
42
44
import type { BaseState , ThunkAction } from '../../../../types'
43
- import type {
44
- HoverOnStepAction ,
45
- SelectMultipleStepsAction ,
46
- } from '../../../../ui/steps'
45
+ import type { SelectMultipleStepsAction } from '../../../../ui/steps'
47
46
48
47
export interface ConnectedStepInfoProps {
49
48
stepId : StepIdType
@@ -54,6 +53,8 @@ export interface ConnectedStepInfoProps {
54
53
sidebarWidth : number
55
54
}
56
55
56
+ const DEBOUNCE_DURATION_MS = 500
57
+
57
58
export function ConnectedStepInfo ( props : ConnectedStepInfoProps ) : JSX . Element {
58
59
const {
59
60
stepId,
@@ -111,14 +112,18 @@ export function ConnectedStepInfo(props: ConnectedStepInfoProps): JSX.Element {
111
112
) : ThunkAction < SelectMultipleStepsAction > =>
112
113
dispatch ( stepsActions . selectMultipleSteps ( steps , lastSelected ) )
113
114
115
+ const debouncedUnhighlightStep = useMemo (
116
+ ( ) =>
117
+ debounce ( ( ) => {
118
+ dispatch ( stepsActions . hoverOnStep ( null ) )
119
+ } , DEBOUNCE_DURATION_MS ) ,
120
+ [ dispatch ]
121
+ )
122
+
114
123
const selectStep = ( ) : ThunkAction < any > =>
115
124
dispatch ( stepsActions . resetSelectStep ( stepId ) )
116
125
const selectStepOnDoubleClick = ( ) : ThunkAction < any > =>
117
126
dispatch ( stepsActions . selectStep ( stepId ) )
118
- const highlightStep = ( ) : HoverOnStepAction =>
119
- dispatch ( stepsActions . hoverOnStep ( stepId ) )
120
- const unhighlightStep = ( ) : HoverOnStepAction =>
121
- dispatch ( stepsActions . hoverOnStep ( null ) )
122
127
const handleSelectStep = ( event : MouseEvent ) : void => {
123
128
if ( selectedStep !== stepId ) {
124
129
dispatch ( toggleViewSubstep ( null ) )
@@ -196,6 +201,21 @@ export function ConnectedStepInfo(props: ConnectedStepInfoProps): JSX.Element {
196
201
197
202
const iconName = stepIconsByType [ step . stepType ]
198
203
204
+ const handleMouseEnter = ( ) : void => {
205
+ debouncedUnhighlightStep . cancel ( )
206
+ dispatch ( stepsActions . hoverOnStep ( stepId ) )
207
+ }
208
+
209
+ const handleMouseLeave = ( ) : void => {
210
+ debouncedUnhighlightStep ( )
211
+ }
212
+
213
+ useEffect ( ( ) => {
214
+ return ( ) => {
215
+ debouncedUnhighlightStep . cancel ( )
216
+ }
217
+ } , [ debouncedUnhighlightStep , hoveredStep , stepId ] )
218
+
199
219
return (
200
220
< >
201
221
{ showConfirmationDoubleClick && (
@@ -218,12 +238,12 @@ export function ConnectedStepInfo(props: ConnectedStepInfoProps): JSX.Element {
218
238
hasError = { hasError }
219
239
isStepAfterError = { stepAfterError }
220
240
stepId = { stepId }
221
- onMouseLeave = { unhighlightStep }
241
+ onMouseLeave = { handleMouseLeave }
222
242
selected = { selected }
223
243
onDoubleClick = { confirmDoubleClick }
224
244
onClick = { confirm }
225
245
hovered = { hoveredStep === stepId && ! hoveredSubstep }
226
- onMouseEnter = { highlightStep }
246
+ onMouseEnter = { handleMouseEnter }
227
247
iconName = { hasError || hasWarnings ? 'alert-circle' : iconName }
228
248
title = { `${ stepNumber } . ${
229
249
i18n . format ( step . stepName , 'titleCase' ) ||
0 commit comments