component 05 / 28WORKING
SC Typewriter Title
- type
- Code Component
- platform
- Framer
- last update
- license
- SecretoCho Design
demo · runs with JavaScript
Type & erase rotating phrases next to a fixed title—fast to configure, accessible, and performant.
A configurable typewriter headline for Framer. Displays a fixed lead-in plus a rotating list of phrases, typed and erased with a blinking caret. Tunable typing speed, hold time, caret style, layout (inline/stacked), and full typography controls.
- UI
- Typography
- Text
- Motion
Main
Overview
- Built With
- React (hooks), CSS (inline), Framer Code Component API
- Layout Support
- Responsive; inline or vertical stacking
- Orientation
- Text-only, left-to-right sequence
- Ideal Use Case
- Hero headings, landing page taglines, product slogans
Tags
Code comment
/* * SC Typewriter Title * © SecretoCho Design 2025 (https://secretocho.design) * A flexible headline that types & deletes rotating phrases with a blinking caret. * Time-based state machine using setTimeout/setInterval; no heavy libs. * @framerDisableUnlink * @framerIntrinsicWidth 480 * @framerIntrinsicHeight 120 */Dependencies
- Technologies
- None (pure React + timers)
- Notes
- No external motion libraries; uses setTimeout/setInterval.
Complexity
- Logic Level
- Medium (typed/deleted state machine, timers, looping)
- Runtime Cost
- Very Low (string slicing; no RAF)
- Component Size
- ~3–4 KB TSX
- Notes
- Timers are cleaned on unmount to prevent leaks.
Guide
Instructions
- Add to your Framer project and place on the canvas.
- Set Fixed Text (mainTitle) and Rotating Phrases (animatedTitles).
- Adjust Typing Speed, Display Duration (hold), Initial Delay, and Repeat.
- Style with Typography, Fixed/Animated Text Color, and Cursor Style.
- Choose Text Arrangement: inline (side-by-side) or stacked (new line).
Examples / Presets
Preset A – Default Hero
“Designs that” + phrases: “convert & captivate” … speed=60ms, hold=1600ms, caret |
Preset B – Fast Tagline
- speed
- 30ms
- hold
- 800ms
- blink
- 300ms
- layout
- inline
Preset C – Minimal Stacked
layout=stacked, fontSize=32, caret _, colors: main #111, animated #555
Mechanics
How it Works
- Maintains index (phrase), subIndex (char position), and deleting flags.
- Typing/deleting steps scheduled with setTimeout(typeSpeed).
- After fully typed, waits holdTime then switches to deleting.
- On reaching 0 chars, advances to next phrase; loops if loop=true.
- Caret blinking toggled via setInterval(caretBlinkSpeed); blink is CSS opacity.
Performance & Tuning
- Typing uses setTimeout; no layout thrash; safe for most devices.
- Smaller typeSpeed = faster typing; tune holdTime for rhythm.
- Long strings are fine; avoid extremely large phrase arrays for readability.
Compatibility & Limits
- Modern browsers; no WebGL/RAF required.
- Uses inline styles; adopt tokens if you need theme-wide control.
- Text renders as real DOM text (copyable/selectable).
Quality
Accessibility
- Pure text output; readable by screen readers.
- Motion sensitivity: consider exposing a toggle or respecting prefers-reduced-motion (pause typing & caret).
- Ensure color contrast for both fixed and animated text.
Security & Privacy
- No network calls or storage.
- No dangerouslySetInnerHTML or eval.
- All timers are cleared on unmount.
Reference
Props
| name | type | default | description |
|---|---|---|---|
mainTitle | string | “Designs that” | Static lead-in text that never changes. |
animatedTitles | string | “convert & captivate” | Array of phrases to type and erase in order. |
font | FontStyle | family:“Inter” | Typography for both fixed and animated segments. |
mainColor | color | ”#000000” | Color for the fixed text. |
animatedColor | color | ”#333333” | Color for the animated text. |
caretChar | enum | ”|” | Caret glyph used during typing. |
caretBlinkSpeed | number | 500 | Blink interval for caret visibility. |
typeSpeed | number | 60 | Delay between each typed/deleted character. |
holdTime | number | 1600 | Time to keep a phrase fully typed before deleting. |
startDelay | number | 300 | Initial wait before starting the typing cycle. |
loop | boolean | true | If false, stops after the last phrase. |
layout | enum | “inline” | Inline places phrases next to the fixed text; stacked puts them on a new line. |
Notes & Tips
- Shorter, high-impact phrases work best for scanning.
- For tighter layouts, reduce fontSize and set layout="stacked".
- To pause after the last phrase (non-loop), set loop=false.
Troubleshooting / FAQ
Caret not blinking
Check caretBlinkSpeed (>0) and that component is mounted.
Animation never starts
Ensure startDelay isn’t too high; confirm animatedTitles isn’t empty.
Stops on last phrase
Expected when loop=false.
Source
Header comment
/* * TypewriterTitle.tsx – Framer Code Component * ----------------------------------------------------------- * A highly‑configurable headline that reveals an array of sub‑titles * via a typewriter animation + blinking caret. * * © SecretoCho Design – July 2025 * @framerDisableUnlink * @framerIntrinsicWidth 480 * @framerIntrinsicHeight 120 */Key excerpt
One step function: type to the end, hold, delete to the start, then move to the next phrase; a timer re-arms it at the typing speed.
// --------------------------------------------------------- const step = useCallback(() => { const phrase = animatedTitles[index] || "" const atEnd = subIndex === phrase.length const atStart = subIndex === 0 if (atEnd && !deleting) { // hold before deleting typeTimer.current = setTimeout(() => setDeleting(true), holdTime) return } if (atStart && deleting) { // next phrase / loop setDeleting(false) setIndex((prev) => { const next = prev + 1 if (next < animatedTitles.length) return next return loop ? 0 : prev }) return } // continue typing or deleting setSubIndex((prev) => prev + (deleting ? -1 : 1)) typeTimer.current = setTimeout(step, typeSpeed) }, [animatedTitles, deleting, holdTime, index, loop, subIndex, typeSpeed]) // Start typing useEffect(() => { typeTimer.current = setTimeout(step, startDelay) return () => { if (typeTimer.current) clearTimeout(typeTimer.current) } }, [step, startDelay])Credits
Credits
Implementation & Framer adaptation by SecretoCho Design.
- license
- SecretoCho Design
SecretoCho Design 2025
Disclaimer
Provided “as is” for visual/UX purposes. Validate accessibility (contrast, motion), and performance within your layout.
Proves
Hiring a design engineer?
I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.
sc@secretocho.design