For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. The asciicn agent skill, for building any ASCII effect on the engine, is at /.well-known/agent-skills/asciicn/SKILL.md.

Typewriter text

Terminal typing with uneven keystrokes, a block, underscore or bar cursor, an optional prompt and backspacing through a list of phrases.

Controls
Cursor
Speed16 cps
Jitter60%
Prompt
Backspace

Installation

pnpm dlx shadcn@latest add https://asciicn.dev/r/typewriter-text.json

Usage

import { TypewriterText } from "@/components/asciicn/typewriter-text";
 
export function Install() {
  return (
    <TypewriterText
      as="p"
      prompt="$ "
      phrases={["pnpm add asciicn", "pnpm dev"]}
      className="font-mono"
    />
  );
}

Characters land one at a time, speed per second on average. jitter makes the gaps uneven: a little longer after a space, longer still after punctuation, and now and then a short hesitation. Each finished phrase holds for pause seconds, then backspaces at backspaceSpeed and the next one starts. After the last phrase it starts over, unless loop is false.

The cursor is a glyph from the glyph font: █, _ or ▏. It stays solid while keys land and blinks in steps while it waits, as a terminal cursor does.

Examples

Rotating headline

One TypewriterText on the second line of a heading, cycling phrases behind an orange underscore cursor. The element takes the size of its longest phrase, so the heading does not reflow while it types.

Boot log

Three log lines with loop={false} and staggered delays, then a ready line. showCursor="typing" shows each log line's cursor only while it types. The ready line uses "started", so its cursor appears with its first key and keeps blinking.

Props

PropTypeDefault
phrases

The lines to type, in order. Screen readers get all of them.

Type: readonly string[]Default –
as

The element to render.

Type: "h1" | "h2" | "h3" | "h4" | "p" | "span" | "div"Default "span"
speed

Characters typed per second, on average.

Type: numberDefault 16
backspaceSpeed

Characters erased per second when backspacing.

Type: numberDefault 40
jitter

How uneven the typing is, from 0 (even) to 1.

Type: numberDefault 0.6
pause

Seconds to hold a typed phrase before erasing it.

Type: numberDefault 1.8
delay

Seconds to wait before the first key.

Type: numberDefault 0.2
backspace

Erase phrases one character at a time. false clears the line at once.

Type: booleanDefault true
loop

Start over after the last phrase. false stops on the last phrase.

Type: booleanDefault true
cursor

Cursor shape: █, _ or ▏.

Type: "block" | "underscore" | "bar"Default "block"
showCursor

When the cursor shows: always, from the first key on, or only while keys land.

Type: "always" | "started" | "typing"Default "always"
prompt

Text before the typed line that is never erased, such as "$ ".

Type: stringDefault –
cursorColor

Cursor colour.

Type: AsciiColorDefault "ink"
promptColor

Prompt colour.

Type: AsciiColorDefault "grey"

Other props pass through to the element.

Notes

  • Every phrase is laid out invisibly in the same grid cell as the typed line, so the element always takes the size of its longest phrase. Typing and erasing never move the text around it.
  • Screen readers get every phrase once, from a visually hidden copy. The typed line is aria-hidden, so a screen reader does not read each keystroke.
  • With reduced motion nothing types and the cursor does not blink. The text shows in full: the first phrase when loop is on, the last phrase when it is off.
  • Typing stops while the text is offscreen or the tab is hidden, and carries on from the same character when it comes back.
  • Changing phrases starts over from the first phrase.