diff --git a/frontend/components/block-state-tracker/slow-motion-control.tsx b/frontend/components/block-state-tracker/slow-motion-control.tsx
index 10a5927..b2a1384 100644
--- a/frontend/components/block-state-tracker/slow-motion-control.tsx
+++ b/frontend/components/block-state-tracker/slow-motion-control.tsx
@@ -1,6 +1,12 @@
'use client'
import { Timer, X } from 'lucide-react'
+import type { ReactElement } from 'react'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from '@/components/ui/tooltip'
interface SlowMotionControlProps {
isActive: boolean
@@ -9,6 +15,23 @@ interface SlowMotionControlProps {
onStop: () => void
}
+function SlowModeTooltipWrapper({ children }: { children: ReactElement }) {
+ return (
+
+ {children}
+
+
+ Slow mode doesn't affect the chain. It only slows UI updates, so the
+ display may lag behind the chain tip.
+
+
+
+ )
+}
+
export function SlowMotionControl({
isActive,
remainingSeconds,
@@ -17,33 +40,36 @@ export function SlowMotionControl({
}: SlowMotionControlProps) {
if (isActive) {
return (
-
-
-
-
Slow Mode
-
({remainingSeconds}s)
+
+
+
+
+ Slow Mode
+ ({remainingSeconds}s)
+
+
-
-
+
)
}
return (
-
+
+
+
)
}
diff --git a/frontend/constants/block-state.ts b/frontend/constants/block-state.ts
index 2b29afd..7538b24 100644
--- a/frontend/constants/block-state.ts
+++ b/frontend/constants/block-state.ts
@@ -1,7 +1,8 @@
import type { BlockState } from '@/types/block'
export const SLOW_MOTION_DURATION_SECONDS = 30
-export const SLOW_MOTION_EVENT_INTERVAL_MS = 75
+export const SLOW_MOTION_CHUNK_INTERVAL_MS = 2000
+export const SLOW_MOTION_CHUNK_NEW_BLOCKS = 2
/**
* Color tokens for block states (CSS variables for consistency).
diff --git a/frontend/hooks/use-blockchain-slow-motion.ts b/frontend/hooks/use-blockchain-slow-motion.ts
index 2631ec8..32708e6 100644
--- a/frontend/hooks/use-blockchain-slow-motion.ts
+++ b/frontend/hooks/use-blockchain-slow-motion.ts
@@ -2,8 +2,9 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import {
+ SLOW_MOTION_CHUNK_INTERVAL_MS,
+ SLOW_MOTION_CHUNK_NEW_BLOCKS,
SLOW_MOTION_DURATION_SECONDS,
- SLOW_MOTION_EVENT_INTERVAL_MS,
} from '@/constants/block-state'
import type { SerializableEventData } from '@/types/events'
@@ -93,14 +94,30 @@ export function useBlockchainSlowMotion({
eventQueueRef.current = []
// Start the slow processing interval
+ // Process queued events in chunks so the UI advances in visible steps.
+ // A "chunk" aims to include ~N new events (BlockStart events) plus any subsequent state transitions for those blocks that are already queued.
processIntervalRef.current = setInterval(() => {
- if (eventQueueRef.current.length > 0) {
- const event = eventQueueRef.current.shift()
- if (event) {
- onProcessEventRef.current(event)
+ if (eventQueueRef.current.length === 0) return
+
+ const chunk: SerializableEventData[] = []
+ let newBlocksInChunk = 0
+
+ while (
+ eventQueueRef.current.length > 0 &&
+ newBlocksInChunk < SLOW_MOTION_CHUNK_NEW_BLOCKS
+ ) {
+ const next = eventQueueRef.current.shift()
+ if (!next) break
+ chunk.push(next)
+ if (next.payload.type === 'BlockStart') {
+ newBlocksInChunk += 1
}
}
- }, SLOW_MOTION_EVENT_INTERVAL_MS)
+
+ if (chunk.length > 0) {
+ onFlushEventsRef.current(chunk)
+ }
+ }, SLOW_MOTION_CHUNK_INTERVAL_MS)
// Start the countdown timer using timestamp-based calculation
countdownIntervalRef.current = setInterval(updateRemainingSeconds, 1000)