saccade
v0.1.0
Published
Slow down time to inspect animations and interactions
Readme
saccade
Saccade is a drop-in animation inspector for web apps. Slow down time, record interactions, scrub through transitions frame-by-frame, and copy structured animation state for AI coding agents.
Install
npm install saccade -DUsage
import { Saccade } from 'saccade'
function App() {
return (
<>
<YourApp />
<Saccade />
</>
)
}A floating panel appears in the corner. Use it to control speed, record, and scrub.
Features
- Speed control — Slow down or speed up all animations (CSS transitions, CSS animations, JS timers,
requestAnimationFrame, video/audio) - Timeline recording — Record interactions, then scrub through captured frames to inspect mid-transition states
- LLM export — Copy structured animation state (properties, keyframes, easing, progress) as markdown for AI coding agents
- Shadow DOM isolation — Panel styles never leak into your app
- Auto-stop — Recording caps at 60s / 3600 frames, and stops when the tab is hidden
- Zero config — Drop in the component and go
How it works
Saccade patches timing APIs (setTimeout, setInterval, requestAnimationFrame, performance.now, Date.now) to scale time by a configurable factor. During recording, it snapshots computed styles, attributes, and animation state every frame. In scrub mode, it replays those snapshots by applying inline styles directly to the DOM.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'bottom-left' | Panel position |
Core API
For non-React usage or programmatic control:
import { SaccadeEngine } from 'saccade/core'
const engine = new SaccadeEngine()
// Speed control
engine.setSpeed(0.25) // quarter speed
engine.getSpeed()
// Recording
engine.startRecording()
const capture = engine.stopRecording()
// Scrubbing
engine.seekTo(500) // seek to 500ms
engine.release()
// Export
const markdown = engine.exportForLLM(500, 'active', 'standard')
// Cleanup
engine.destroy()React Hooks
import { SaccadeProvider, useSaccadeEngine, useTimeline, useSpeed } from 'saccade'useSpeed
const { speed, isPaused, setSpeed, togglePause } = useSpeed()useTimeline
const {
state, // 'idle' | 'recording' | 'scrubbing'
capture, // TimelineCapture | null
scrubTime, // current scrub position in ms
startRecording,
stopRecording,
seek,
release,
exportLLM,
} = useTimeline()Export Detail Levels
The LLM export supports four detail levels:
| Level | Description |
|-------|-------------|
| compact | One line per element — property names and timing only |
| standard | Full property values, ranges, interaction state |
| detailed | Adds CSS variables, @keyframes source, transition conflicts |
| forensic | Adds viewport, URL, user agent, device pixel ratio |
Types
import type {
AnimationInfo,
TimelineCapture,
TimelineExport,
FrameSnapshot,
ExportFilter,
OutputDetailLevel,
} from 'saccade'Requirements
- React 18+ (for the
<Saccade>component) - No React dependency needed for
saccade/core
License
MIT
