Add click-to-navigate on ledger entries

Clicking on any non-latest entry in the working problem ledger
navigates back to that step, allowing users to redo from that point.

- Added navigateToStep function that restores state from history
- Ledger entries (except latest) are now clickable with hover effects
- Keyboard accessible (Enter/Space to activate)
- Truncates state history to the restored point

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2026-01-16 14:27:09 -06:00
parent 1dcb1457ef
commit 3c7d83767a

View File

@@ -165,6 +165,51 @@ export function FlowchartWalker({
setWrongDecision(null)
}, [stateHistory, onChangeProblem])
// Navigate to a specific step in the working problem history
// Clicking on ledger entry i takes you to the state right after that entry was created
const navigateToStep = useCallback(
(targetIndex: number) => {
// If clicking the latest entry, do nothing
if (targetIndex >= state.workingProblemHistory.length - 1) {
return
}
// Find the state in history where workingProblemHistory.length === targetIndex + 1
// This is the state right after that entry was created, before any further advances
const targetHistoryIndex = stateHistory.findIndex(
(s) => s.workingProblemHistory.length === targetIndex + 1
)
if (targetHistoryIndex !== -1) {
// Found exact match - restore that state
const targetState = stateHistory[targetHistoryIndex]
setStateHistory((prev) => prev.slice(0, targetHistoryIndex))
setState(targetState)
} else {
// Fallback: find the first state with at least targetIndex + 1 entries
// and manually truncate the workingProblemHistory
const fallbackIndex = stateHistory.findIndex(
(s) => s.workingProblemHistory.length > targetIndex
)
if (fallbackIndex !== -1) {
const baseState = stateHistory[fallbackIndex]
const restoredState: FlowchartState = {
...baseState,
workingProblemHistory: baseState.workingProblemHistory.slice(0, targetIndex + 1),
}
setStateHistory((prev) => prev.slice(0, fallbackIndex))
setState(restoredState)
}
}
setPhase({ type: 'showingNode' })
setWrongAttempts(0)
setWrongDecision(null)
},
[state.workingProblemHistory.length, stateHistory]
)
// =============================================================================
// Handlers
// =============================================================================
@@ -576,7 +621,21 @@ export function FlowchartWalker({
data-testid={`ledger-step-${idx}`}
data-step-index={idx}
data-is-latest={isLatest}
data-is-clickable={!isLatest}
data-node-id={step.nodeId}
onClick={!isLatest ? () => navigateToStep(idx) : undefined}
role={!isLatest ? 'button' : undefined}
tabIndex={!isLatest ? 0 : undefined}
onKeyDown={
!isLatest
? (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
navigateToStep(idx)
}
}
: undefined
}
className={css({
display: 'flex',
alignItems: 'center',
@@ -591,6 +650,15 @@ export function FlowchartWalker({
? { base: 'blue.400', _dark: 'blue.500' }
: { base: 'blue.200', _dark: 'blue.700' },
opacity: isLatest ? 1 : 0.7,
cursor: isLatest ? 'default' : 'pointer',
transition: 'all 0.15s ease-out',
_hover: isLatest
? {}
: {
opacity: 1,
backgroundColor: { base: 'blue.50', _dark: 'blue.900/50' },
borderColor: { base: 'blue.300', _dark: 'blue.600' },
},
})}
>
{/* Step number */}