A lightweight, zero-dependency React typewriter component with realistic typing animations.
- Zero dependencies — no CSS-in-JS library required, works right out of the box
- Modern React 19+ — built with hooks and the
react-jsxtransform useTypewriterhook — extract the core engine for fully custom UIs- Declarative actions — composable
type(),pause(),deleteAll(),deleteChars()builders sentencesprop — cycle through an array of strings with one prop- Looping — infinite or N iterations via the
loopprop - Realistic typo simulation — set
mistakeChancefor QWERTY-aware "mistake → correct" animations - Live speed changes — dynamically update
typeSpeed/deleteSpeedmid-animation - Callbacks —
onType,onDelete,onFinish,onLoop - Accessible —
aria-hiddencursor, automaticprefers-reduced-motionsupport - Tree-shakeable ESM — modern
exportsfield withsideEffects: false - Fully typed — comprehensive TypeScript definitions with JSDoc
npm i react-mkimport Typewriter, { Cursor } from 'react-mk';
function App() {
return (
<p>
<Typewriter>Hello World</Typewriter>
<Cursor />
</p>
);
}<Typewriter>Any string or number works here</Typewriter>Use the render-prop pattern to compose typing, pausing, and deleting:
<Typewriter>
{({ type, pause, deleteAll }) => [
type('Hello World'),
pause(2000),
deleteAll(),
type('React MK v2'),
]}
</Typewriter>The sentences prop makes it trivial to cycle through an array of strings:
<Typewriter
sentences={['First sentence', 'Second sentence', 'Third sentence']}
sentenceDelay={2000}
loop
/>For full control, use the hook directly:
import { useTypewriter, type, pause, deleteAll, Cursor } from 'react-mk';
function CustomTypewriter() {
const { text, phase } = useTypewriter(
[type('Hello'), pause(1000), deleteAll(), type('World')],
{ loop: true, typeSpeed: [40, 80] },
);
return (
<h1>
{text}
{phase !== 'complete' && <Cursor />}
</h1>
);
}Add mistakeChance for humanized typing that makes QWERTY-adjacent mistakes and self-corrects:
<Typewriter mistakeChance={0.06} typeSpeed={[60, 120]}>
This text will have occasional realistic typos that get corrected
</Typewriter><Cursor /> {/* Default: blinking | */}
<Cursor blink={false}>_</Cursor> {/* Static underscore */}
<Cursor blinkSpeed={300}>█</Cursor> {/* Fast-blinking block */}| Prop | Type | Default | Description |
|---|---|---|---|
children |
string | number | ((builders) => Action[]) |
— | Content to type or render-prop returning actions |
sentences |
string[] |
— | Array of sentences to cycle through (takes priority over children) |
sentenceDelay |
number |
2000 |
Ms each sentence is shown before deletion |
typeSpeed |
[min, max] |
[50, 90] |
Delay range between keystrokes (ms) |
deleteSpeed |
[min, max] |
[30, 60] |
Delay range between deletions (ms) |
loop |
boolean | number |
false |
true for infinite, or a number for N iterations |
loopDelay |
number |
1000 |
Ms before restarting the loop |
startDelay |
number |
0 |
Ms before the animation begins |
mistakeChance |
number |
0 |
Probability (0–1) of a typo per character |
onType |
(char, text) => void |
— | Called after each character is typed |
onDelete |
(char, text) => void |
— | Called after each character is deleted |
onFinish |
() => void |
— | Called when all actions complete |
onLoop |
(count) => void |
— | Called when the animation loops |
Returns { text, phase, loopCount }.
text— The currently displayed stringphase— One of'idle' | 'typing' | 'deleting' | 'pausing' | 'complete'loopCount— Current loop iteration (0-indexed)
| Prop | Type | Default | Description |
|---|---|---|---|
blink |
boolean |
true |
Enable/disable blink animation |
blinkSpeed |
number |
530 |
Blink cycle duration (ms) |
children |
ReactNode |
| |
Cursor character(s) |
...rest |
HTMLSpanElement props |
— | Spread to the root <span> |
| Builder | Description |
|---|---|
type(text) |
Type a string character by character |
pause(ms) |
Pause for a duration in milliseconds |
deleteAll() |
Delete all currently displayed text |
deleteChars(n) |
Delete n characters from the end |
Keyboard→Typewriter(default export renamed)@emotion/cssremoved — Cursor now uses pure CSS, no imports neededkeyPressDelayRange→typeSpeedsentenceDelayPerCharRange→ Usesentences+sentenceDelaypropsblinkAnimationDuration→blinkSpeedtype()render-prop now returns explicit action objects instead of mixed arrays- New:
useTypewriterhook,deleteChars,loop,mistakeChance, callbacks