Skip to content

AnimateTyping

Text appearing one character at a time. The whole string is in the document from the first frame for a screen reader, and what animates is a copy that is hidden from one.

tsx
import { AnimateTyping } from 'neba';

<AnimateTyping speed={18}>Ship the interface, not the design system.</AnimateTyping>;

Props

PropTypeDefaultDescription
textstringThe text, when it is easier to pass than to nest. Overrides children
speednumber24How fast it is typed, in characters per second
holdnumber1400How long the finished text is held before it repeats, in milliseconds
erasebooleanfalseDeletes the text again before repeating, rather than clearing it in one frame
eraseSpeednumberHow fast it is deleted, in characters per second. Defaults to twice speed
caretbooleantrueThe block after the text
caretCharReactNode'|'What the caret is drawn as
durationsharednumberHow long one run takes, in milliseconds
delaysharednumber0How long before it starts, in milliseconds
easingstringThe easing curve, as CSS writes it. Defaults to the house curve
repeatsharednumber | 'infinite'1How many times it runs
alternatesharedbooleanfalseRuns every other pass backwards, so a repeat returns instead of jumping
triggershared'mount' | 'visible' | 'hover' | 'manual''mount'What starts it. visible is on scrolling into view, hover is under the pointer (focus counts), manual is whatever play says
playbooleanRuns it when trigger is manual. Each false → true starts it over
oncesharedbooleantrueWith trigger="visible", whether it runs only the first time. Off, it runs again on every return
thresholdsharednumber0.2With trigger="visible", how much of the element has to be on screen, from 0 to 1
pausedsharedbooleanfalseHolds the animation where it is
childrenReactNodeThe text to type. Only text is typed: an element among the children contributes its text and nothing about its markup

Every other <div> attribute passes through to the root. The settings shared by every Animate* are defined in prop conventions.

Only text is typed. Pass a string, or strings; an element among the children contributes its text and nothing about its markup, because there is no honest way to reveal half of a link. text is the same thing as a prop, and wins when both are given.

Examples

speed

Characters per second. A speed rather than a duration, because a long line and a short one should be typed at the same pace rather than in the same time: though duration is still accepted, and means the time for the whole string.

repeat, hold and erase

repeat is how many passes it makes and hold is how long the finished text stays up between them. Without erase a repeat clears in one frame, which is right for a line being replaced; with it the text is deleted a character at a time, at eraseSpeed: twice speed by default, which is what a person actually does.

delay

Milliseconds before it starts. A delay per line is what turns a stack of typewriters into a transcript.

caret

The block after the text, on by default. caretChar is what it is drawn as: , _, anything.

tsx
<AnimateTyping caretChar="▌" caret={false}>
  No caret at all
</AnimateTyping>

Accessibility

  • The full text is in the document from the first frame, in a clipped box, and the animated copy is aria-hidden. A screen reader reads the line once and is not made to sit through the performance.
  • A reduced-motion preference shows the whole string immediately, with no typing at all.
  • The box is not laid out from the characters that have arrived, so the text around it does not reflow on every frame.
  • Characters are counted as graphemes, not code points: and 👩‍👩‍👧 each arrive in one step rather than in three or seven.

Released under the MIT License