# <motion-typewriter>

Typewriter text effect. Reveals slotted text character-by-character,
with optional looping (type → hold → erase → retype) and a blinking caret.

**Use it for:** a short line, such as a hero tagline or a prompt, that
should type itself out when it scrolls into view, once or on repeat with
`loop`.

**Avoid it for:** long text, important information and text with links or
other markup, which is removed. For words that take turns in one place,
use `motion-words`.

**Accessibility:** screen readers read the whole text at all times from a
visually hidden copy, even before typing starts and while `loop` erases it.
The typed characters and the caret are `aria-hidden`.

**Reduced motion:** the full text shows at once and nothing is typed. The
caret shows but does not blink; set `cursor="false"` to hide it.

**Common mistakes:** waiting for `motion-finish` or `finished` with `loop`
set: a looping run never finishes on its own. Forgetting that the element
is empty until it types: the content after it moves as the line grows, so
reserve the space in your layout.

Docs: https://www.motion-components.dev/docs/text/motion-typewriter/

## Install

```js
import 'motion-components/motion-typewriter'
```

Or without a build step:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-typewriter.js/+esm"></script>
```

## Example

```html
<motion-typewriter interval="0.04" loop hold="2">
  Hello, world.
</motion-typewriter>
```

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `interval` | `number` | `0.05` | Time between characters while typing, in seconds. |
| `delay` | `number` | `0` | Delay before typing starts after viewport entry, in seconds. |
| `hold` | `number` | `1.8` | Time to hold the finished line before erasing (loop mode), in seconds. |
| `loop` | `boolean` | `false` | When `true`, type → hold → erase → retype on repeat. |
| `gap` | `number` | `0.5` | With `loop`, seconds the line stays empty after erasing before it retypes. |
| `pause-on-hover` | `boolean` | `false` | Pause the loop while the pointer is over the text. |
| `cursor` | `boolean` | `true` | When `true`, render a blinking caret after the typed text. Set `cursor="false"` to hide it. |

## Properties

| Property | Type | Description |
| --- | --- | --- |
| `playState` | `'idle' \| 'running' \| 'paused' \| 'finished'` | Current state: `'idle'`, `'running'`, `'paused'` or `'finished'`. |
| `finished` | `Promise<void>` | Resolves when the current run settles. A new run replaces the promise. |

## Methods

| Method | Description |
| --- | --- |
| `replay()` | Resets and re-runs the typing animation from the start. |
| `play()` | Starts the animation, or resumes it when paused. Resolves once the run settles. Under `prefers-reduced-motion: reduce` the final state is applied immediately without animating. |
| `pause()` | Holds the animation at its current position. No-op unless running. |
| `finish()` | Jumps to the final state and settles. Fires `motion-finish`. |
| `cancel()` | Reverts to the initial state and returns to idle. Fires `motion-cancel`. |

## Events

The `motion-*` events bubble and are composed.

| Event | Description |
| --- | --- |
| `motion-start` | When a run starts. |
| `motion-finish` | When a run finishes, or `finish()` jumps to the end. |
| `motion-cancel` | When `cancel()` stops a run and resets it. |

## Slots

| Slot | Description |
| --- | --- |
| (default) | The text to type. Plain text only — read once on connect. |
