Typing Text

Text typed character by character, with an optional blinking cursor.

<script setup lang="ts">
import { TypingText, TypingTextCursor } from '@animate-ui/vue/primitives/texts/typing'

withDefaults(
  defineProps<{
    delay?: number | string
    holdDelay?: number | string
    loop?: boolean | string
    cursor?: boolean | string
  }>(),
  { delay: 0, holdDelay: 1000, loop: false, cursor: true },
)
</script>

<template>
  <TypingText
    :key="`${delay}-${holdDelay}-${loop}-${cursor}`"
    class="text-4xl font-semibold"
    text="Typing Text component made with Motion. Highly customizable and easy to use."
    :delay="Number(delay)"
    :hold-delay="Number(holdDelay)"
    :loop="loop === true || loop === 'true'"
  >
    <TypingTextCursor
      v-if="cursor === true || cursor === 'true'"
      class="ml-1 h-8! w-1! rounded-full"
    />
  </TypingText>
</template>

Installation

npm install @animate-ui/vue motion-v
pnpm add @animate-ui/vue motion-v
yarn add @animate-ui/vue motion-v
bun add @animate-ui/vue motion-v

Usage

<script setup lang="ts">
import {
  TypingText,
  TypingTextCursor,
} from '@animate-ui/vue/primitives/texts/typing';
</script>

<template>
  <TypingText :text="['Design', 'Build', 'Ship']" loop>
    <TypingTextCursor />
  </TypingText>
</template>

Animation

  • Characters are typed every duration ms (100). With several texts (or loop), a typed text holds for hold-delay, is erased at the same pace, and the next one is typed.
  • The text is written to the DOM directly: typing a character never re-renders Vue. Changing duration or hold-delay mid-animation takes effect without restarting.
  • A loop pauses off screen and in a hidden tab; a single run only in a hidden tab. It resumes where it stopped.
  • The cursor blinks (a 1s on/off loop) while it waits for delay and once a text is typed, and stays solid while typing or erasing (it fades in over 0.3s as typing starts). It holds still off screen and in a hidden tab.
  • Under reduced motion, the text appears at once (the last text, or the first one with loop) and the cursor doesn't blink.
  • Screen readers read every text once, never the partially typed ones.

API Reference

TypingText

PropTypeDefault
text
string | string[]-
duration?
number100
delay?
number0
loop?
booleanfalse
hold-delay?
number1000
in-view?
booleanfalse
in-view-margin?
string'0px'
in-view-once?
booleantrue
...props?
HTMLAttributes-

TypingTextCursor

PropTypeDefault
variants?
Variants-
...props?
Omit<HTMLMotionProps<'span'>, 'children'>-

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/23/2026