Skip to content

Commit

Permalink
refactor(progress-tracker): improves steps rerenderings
Browse files Browse the repository at this point in the history
  • Loading branch information
soykje committed Dec 22, 2023
1 parent f3b89bf commit 8b3d45c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 41 deletions.
52 changes: 24 additions & 28 deletions packages/components/progress-tracker/src/ProgressTrackerStep.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
import {
type ComponentPropsWithoutRef,
forwardRef,
type ReactNode,
useEffect,
useId,
useMemo,
useState,
} from 'react'
import { type ComponentPropsWithoutRef, forwardRef, type ReactNode, useEffect, useId } from 'react'

import {
ProgressTrackerStepContext,
type ProgressTrackerStepContextInterface,
useProgressTrackerContext,
} from './ProgressTrackerContext'
import { ProgressTrackerStepContext, useProgressTrackerContext } from './ProgressTrackerContext'
import { stepButtonVariant, stepItemVariant } from './ProgressTrackerStep.styles'
import { ProgressTrackerStepIndicator } from './ProgressTrackerStepIndicator'

Expand Down Expand Up @@ -43,28 +31,36 @@ export const ProgressTrackerStep = forwardRef<HTMLLIElement, ProgressTrackerStep
const stepId = `step-${ID}`
const stepIndex = [...steps.keys()].indexOf(stepId)

const disabledAfter = useMemo(() => {
const disabledAfter = (() => {
const nextStepId = [...steps.keys()][stepIndex + 1]

return !!(nextStepId && steps.get(nextStepId)?.includes('disabled'))
}, [steps, stepIndex])
})()

const [progressState, setProgressState] =
useState<ProgressTrackerStepContextInterface['state']>('incomplete')
const progressState = (() => {
if (stepIndex === currentStepIndex) return 'active'
else if (stepIndex < currentStepIndex) return 'complete'
else return 'incomplete'
})()

useEffect(() => {
setSteps(steps => steps.set(stepId, [progressState, disabled ? 'disabled' : '']))
}, [disabled, stepId, setSteps, progressState])
setSteps(steps => {
const newSteps = new Map(steps)

useEffect(() => {
if (stepIndex === currentStepIndex) {
setProgressState('active')
} else if (stepIndex < currentStepIndex) {
setProgressState('complete')
} else {
setProgressState('incomplete')
return newSteps.set(
stepId,
[progressState, disabled ? 'disabled' : ''].filter(v => !!v)
)
})

return () => {
setSteps(steps => {
steps.delete(stepId)

return steps
})
}
}, [currentStepIndex, stepIndex])
}, [disabled, stepId, setSteps, progressState])

return (
<li
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ type ProgressTrackerStepIndicatorProps = ComponentPropsWithoutRef<'span'> & {
incomplete?: ReactNode
}

const CompleteIndicator = () => (
<Icon size="sm">
<Check />
</Icon>
)

export const ProgressTrackerStepIndicator = ({
complete,
incomplete,
Expand All @@ -27,19 +33,8 @@ export const ProgressTrackerStepIndicator = ({
<span className={stepIndicatorVariant({ size, state, className })} aria-hidden="true">
{size !== 'sm' && (
<>
{state === 'complete' ? (
<>
{complete === undefined ? (
<Icon size="sm">
<Check />
</Icon>
) : (
complete
)}
</>
) : (
<>{incomplete === undefined ? index + 1 : incomplete}</>
)}
{state === 'complete' && (complete === undefined ? <CompleteIndicator /> : complete)}
{state !== 'complete' && (incomplete === undefined ? `${index + 1}` : incomplete)}
</>
)}
</span>
Expand Down

0 comments on commit 8b3d45c

Please sign in to comment.