| name | prompt-typewriter |
| description | motion-graphic primitive — character-by-character text reveal at constant rate. mechanical, no easing. canonical sp-f product-demo idiom for "user types a prompt" beat. renderer = hyperframe-gsap (linear character pacing renders most naturally in html). |
prompt-typewriter
Purpose
Reveal text character-by-character at a steady rate, mimicking a real user typing. Linear pacing — NO easing — because the goal is to feel mechanical / human, not animated.
Params
{
"full_text": "Build a trip planning app that organizes destinations…",
"chars_per_frame": 0.33,
"delay_before_first_char_frames": 12,
"delay_after_last_char_frames": 18,
"cursor": {
"show": true,
"blink_period_frames": 30,
"color": "#1A1A1A",
"width_px": 2,
"height_em": 1.2
},
"font_family": "Inter",
"font_size_px": 22,
"color": "#1A1A1A",
"line_height": 1.4
}
Behaviour
- After
delay_before_first_char_frames, start revealing characters.
- Number of characters revealed at frame F:
floor((F - delay) * chars_per_frame).
- After full text revealed, wait
delay_after_last_char_frames before the next phase.
- Cursor blinks at
blink_period_frames cycle, positioned at the end of revealed text.
Implementation: a React component using useCurrentFrame() and string slicing.
Style pack overrides
- SP-F (product-demo) — canonical use. Inside a prompt card with the cursor visible.
Quality Checks
- Linear pacing (no easing, no speedup, no slowdown).
- Cursor blinks at a reasonable cadence (~1Hz).
- Text wraps appropriately within the container width.
- Full text revealed BEFORE scene ends (with buffer for cursor-puppet).
Failure Modes
- Typing accelerates or decelerates. Use integer truncation of frame * rate; don't apply easing.
- Cursor doesn't blink. Verify blink period via modulo.
- Cursor position lags behind text. Cursor x-position must match the rendered length of revealed text — use
getBoundingClientRect() or compute via font metrics.
- Text overflows container. Constrain by container width and pre-test wrapping.