# React

> Add a handwriting animation to a React or Next.js app with the TegakiRenderer component: controlled time, effects, streaming text and the imperative handle.

Source: https://tegaki.ink/frameworks/react/

Tegaki's default export is a React component that supports SSR, streaming text, and imperative playback control.

## Installation

```sh
npm install tegaki react react-dom
```

## Basic example

```tsx
import { TegakiRenderer } from 'tegaki';
import bundle from 'tegaki/fonts/caveat';

function App() {
  return (
    <TegakiRenderer
      font={bundle}
      time={{ mode: 'uncontrolled', speed: 1, loop: true }}
      style={{ fontSize: 48 }}
    >
      Hello World
    </TegakiRenderer>
  );
}
```

> **Using Vite 7 or earlier?**
>
> If the text doesn't draw in `vite dev` (you can select it, or see it with `showOverlay`, but nothing animates), add `optimizeDeps: { exclude: ['tegaki'] }` to `vite.config.ts` and restart the dev server. See [Bundler Setup](https://tegaki.ink/guides/bundlers/#vite).

## Controlled time

Drive the animation from external state:

```tsx
import { useState } from 'react';
import { TegakiRenderer } from 'tegaki';
import bundle from 'tegaki/fonts/caveat';

function App() {
  const [time, setTime] = useState(0);

  return (
    <>
      <input
        type="range"
        min={0}
        max={10}
        step={0.01}
        value={time}
        onChange={(e) => setTime(Number(e.target.value))}
      />
      <TegakiRenderer font={bundle} time={time} style={{ fontSize: 48 }}>
        Scrub me!
      </TegakiRenderer>
    </>
  );
}
```

## Imperative handle

Access the engine instance via `ref`:

```tsx
import { useRef } from 'react';
import { TegakiRenderer, type TegakiRendererHandle } from 'tegaki';
import bundle from 'tegaki/fonts/caveat';

function App() {
  const ref = useRef<TegakiRendererHandle>(null);

  return (
    <TegakiRenderer
      ref={ref}
      font={bundle}
      time={{ mode: 'uncontrolled', speed: 1 }}
      style={{ fontSize: 48 }}
    >
      Hello World
    </TegakiRenderer>
  );
}
```

The handle exposes:

- `ref.current.engine`: the `TegakiEngine` instance (or `null` before mount)
- `ref.current.element`: the container `HTMLDivElement`

## Effects

```tsx
<TegakiRenderer
  font={bundle}
  time={{ mode: 'uncontrolled', speed: 1, loop: true }}
  effects={{
    glow: { radius: 8, color: '#00ccff' },
    pressureWidth: true,
    strokeGradient: { colors: 'rainbow' },
  }}
  style={{ fontSize: 48 }}
>
  Fancy effects
</TegakiRenderer>
```

## Streaming text

For AI chat interfaces, where text arrives a chunk at a time:

```tsx
function StreamingMessage({ text }) {
  return (
    <TegakiRenderer
      font={bundle}
      time={{ mode: 'uncontrolled', speed: 4, catchUp: 0.5 }}
      style={{ fontSize: 32 }}
    >
      {text}
    </TegakiRenderer>
  );
}
```

See [Streaming Text](https://tegaki.ink/guides/streaming/) for more details.
