shadcn.io is not affiliated with official shadcn/ui
Typing Text types a line out one character at a time behind a caret, the way a person would: each keystroke's wait varies a little, and the caret blinks only while it waits. Give it several lines and it types one, pauses, deletes it and types the next, round and round.
Use it for a hero line that cycles through what a product is for, a command in a terminal mock-up, or a prompt being written. To swap whole words in place instead, use Flip Words or Rotating Text; to delete and correct a line, Backspace Text. A small timer moves it one step at a time and a CSS keyframe animation blinks the caret, with no animation library; with reduced motion each line shows whole.
Installation
Usage
import { TypingText } from "@/components/ui/typing-text";<TypingText text={["Components you own.", "Ship it this afternoon."]} />Demos
Cursor
cursor is the caret's shape: bar, the default, block or underscore, drawn in the text's colour, or none. Style it further through data-slot="typing-text-cursor".
Colors
colors gives each line its own colour, in turn, any CSS colour or theme variable. The text sits inline in a sentence like any other word.
Terminal
trigger="view" waits, caret blinking, until the text scrolls into view. delay is the wait before the first character, speed the average time per character, and onComplete is called once the last line is typed: here it shows the command's output.
Accessibility
Screen readers read every line once, in full, from a visually hidden copy, never the half-typed characters; the typed text and the caret are hidden from them. The caret blinks once a second, well under the three flashes a second that can trigger seizures, and stops with reduced motion, where each line shows whole.
FAQ
How do several lines cycle?
Pass an array to text. Each line is typed, stays for pause (1800 ms by default), is deleted at deleteSpeed, and the next one is typed. After the last line it starts over; with loop={false} it stops on the last line, typed.
Why does the typing speed vary?
A person never types at an even pace, so each keystroke waits speed give or take jitter (half of it by default). The variation is worked out from the character's place, not drawn at random, so it types the same way on every visit. jitter={0} types like a metronome.
Why doesn't the caret blink while typing?
Because a real one doesn't: it stays solid while characters arrive and blinks once the typing waits, at a pause, at the end, or before it starts.
Will the text around it move as it types?
It grows like any text, so in a centred heading the line re-centres as it types. To hold the layout, give its container a fixed width or a min-h that fits the longest line.
API Reference
TypingText
<span> data-slot="typing-text"
textstring | string[]
The text, or several lines typed and deleted in turn.
- Type
string | string[]
colors?string[]
Colours the lines take in turn, any CSS colour; the text's own colour when unset.
cursor?"bar" | "block" | "underscore" | "none"
The caret after the text. @default "bar".
- Type
"bar" | "block" | "underscore" | "none"- Default
"bar"
delay?number
The wait before the first character, in milliseconds. @default 0.
- Default
0
deleteSpeed?number
The time to delete one character, in milliseconds. @default 30.
- Default
30
jitter?number
How much each keystroke's wait varies, from 0 (even) to 1. @default 0.5.
- Default
0.5
loop?boolean
Whether several lines start over after the last; a single line is typed once.
- Default
true
onComplete?() → void
Called once the typing is over: the last line typed, when it doesn't loop.
- Returns
void
pause?number
How long a typed line stays before it's deleted, in milliseconds. @default 1800.
- Default
1800
speed?number
The time to type one character, on average, in milliseconds. @default 60.
- Default
60
trigger?"mount" | "view"
When the typing starts: as soon as the page shows it, or once it scrolls into view. @default "mount".
- Type
"mount" | "view"- Default
"mount"
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
data-state?string--typing-text-colorstring
The colour of the current line (from colors).
Related
Flip Words
CyclingSwap whole words in place instead
Rotating Text
CyclingWords that roll through like a reel
- Pro
Backspace Text
CyclingDelete only as far as the correction
- Pro
Terminal Text
EntranceCommands typed, then their output
Text Generate Effect
EntranceA reply that sharpens word by word
- Pro
Writing Text
EntranceWords at the pace of reading aloud