Fix: Animated scrollbar renders black in NO_COLOR mode (#13188)

This commit is contained in:
Jacob Richman
2025-11-16 20:45:07 -08:00
committed by GitHub
parent cf8de02c68
commit 78a28bfc01
9 changed files with 202 additions and 44 deletions
@@ -70,4 +70,32 @@ describe('useAnimatedScrollbar', () => {
expect(debugState.debugNumAnimatedComponents).toBe(0);
});
it('should not crash if Date.now() goes backwards (regression test)', async () => {
// Only fake timers, keep Date real so we can mock it manually
vi.useFakeTimers({
toFake: ['setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'],
});
const dateSpy = vi.spyOn(Date, 'now');
let currentTime = 1000;
dateSpy.mockImplementation(() => currentTime);
const { rerender } = render(<TestComponent isFocused={false} />);
// Start animation. This captures start = 1000.
rerender(<TestComponent isFocused={true} />);
// Simulate time going backwards before the next frame
currentTime = 900;
// Trigger the interval (33ms)
await act(async () => {
vi.advanceTimersByTime(50);
});
// If it didn't crash, we are good.
// Cleanup
dateSpy.mockRestore();
// Reset timers to default full fake for other tests (handled by afterEach/beforeEach usually, but here we overrode it)
});
});
@@ -49,11 +49,15 @@ export function useAnimatedScrollbar(
const unfocusedColor = theme.ui.dark;
const startColor = colorRef.current;
if (!focusedColor || !unfocusedColor) {
return;
}
// Phase 1: Fade In
let start = Date.now();
const animateFadeIn = () => {
const elapsed = Date.now() - start;
const progress = Math.min(elapsed / fadeInDuration, 1);
const progress = Math.max(0, Math.min(elapsed / fadeInDuration, 1));
setScrollbarColor(interpolateColor(startColor, focusedColor, progress));
@@ -69,7 +73,10 @@ export function useAnimatedScrollbar(
start = Date.now();
const animateFadeOut = () => {
const elapsed = Date.now() - start;
const progress = Math.min(elapsed / fadeOutDuration, 1);
const progress = Math.max(
0,
Math.min(elapsed / fadeOutDuration, 1),
);
setScrollbarColor(
interpolateColor(focusedColor, unfocusedColor, progress),
);