Overlay types
Per-frame typing and tap effects.
Overlays are visuals layered on top of a captured frame for the duration of that frame. They're useful for content that wasn't in the captured DOM at all — a fake-typed search query, a click ripple — without needing to capture intermediate states.
type Overlay = TypingOverlay | TapOverlay;
TypingOverlay
interface TypingOverlay { kind: "typing"; text: string; x: number; y: number; fontSize?: number; color?: string; delay?: number; speed?: number; bgColor?: string; bgWidth?: number; bgHeight?: number; }
"typing"#e6edf3)bgWidth / bgHeight default to enclose the typed text.How it animates
The overlay renders the full text once with an animated SVG
<clipPath> whose width grows from 0 to the full string
width over text.length × speed ms. After the type-out completes,
the text holds visible until the frame ends.
Example
{
kind: "typing",
text: "sk install error-handling",
x: 24, y: 32,
fontSize: 13,
color: "#e6edf3",
speed: 40,
bgColor: "#1e1e2e",
}
TapOverlay
interface TapOverlay { kind: "tap"; x: number; y: number; delay?: number; }
"tap"Renders a Material-style ripple: a small white-translucent dot that fades in over 20 ms, plus an expanding ring that grows to ~35 px radius and fades over 500 ms. Useful for "user clicks here" cues, especially on captured mobile UIs.
Example
{ kind: "tap", x: 320, y: 220, delay: 800 }
Important: overlays disable the merge fast path
If any frame has overlays,
generateAnimatedSvg falls
back to per-frame-atomic rendering. For all-crossfade sequences this typically
means a slightly larger SVG with a small risk of one-frame flicker on the
transition. Two ways to avoid it:
- Capture the typed state instead. If the typed text could just be part of the captured HTML, put it there.
- Use overlays only on the frame that needs them. The fast path requires all transitions to be crossfade and no overlays anywhere — so even one overlay forces the fallback for the whole sequence.