# Rendering Animations

> Display handwriting animations with Tegaki: styling, the controlled, uncontrolled and CSS time modes, effects and streaming text.

Source: https://tegaki.ink/guides/rendering/

Tegaki handles text layout, line wrapping, and animation playback. See the [framework guides](https://tegaki.ink/frameworks/react/) for framework-specific setup.

## Basic usage

**React**

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

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

**Svelte**

```svelte
<script>
  import { TegakiRenderer } from 'tegaki/svelte';
  import bundle from 'tegaki/fonts/caveat';
</script>

<TegakiRenderer
  font={bundle}
  text="Hello World"
  time={{ mode: 'uncontrolled', speed: 1, loop: true }}
  style="font-size: 48px"
/>
```

**Vue**

```vue
<script setup>
import { TegakiRenderer } from 'tegaki/vue';
import bundle from 'tegaki/fonts/caveat';
</script>

<template>
  <TegakiRenderer
    :font="bundle"
    text="Hello World"
    :time="{ mode: 'uncontrolled', speed: 1, loop: true }"
    :style="{ fontSize: '48px' }"
  />
</template>
```

**Vanilla JS**

```js
import { TegakiEngine } from 'tegaki/core';
import bundle from 'tegaki/fonts/caveat';

new TegakiEngine(document.getElementById('tegaki'), {
  text: 'Hello World',
  font: bundle,
  time: { mode: 'uncontrolled', speed: 1, loop: true },
});
```

## Styling

Tegaki reads its typography from the container's own CSS. Set `font-size`,
`line-height`, `color`, and `letter-spacing` however you normally would (inline
style, a class, a CSS variable) and the renderer picks them up, re-measuring
when they change. `letter-spacing` is applied to the animated strokes just as
the browser would space static text, so spacing, line wrapping, and the drawn
glyphs stay in sync. `line-height: normal` gives the font's own line spacing:
it differs from font to font (Tangerine sets lines 1em apart, Amiri 1.76em) and
is measured from the browser, so the strokes land where the text would. Most
pages inherit a fixed `line-height` (Tailwind's base styles set 1.5), which is
loose for handwriting fonts with small letters; set `normal` or a smaller ratio
on the renderer to tighten it.

```tsx
<TegakiRenderer font={bundle} style={{ fontSize: 48, letterSpacing: '0.1em', color: '#3b82f6' }}>
  Hello World
</TegakiRenderer>
```

## Time control modes

### Uncontrolled

The component manages its own animation clock:

```ts
time: { mode: 'uncontrolled', speed: 2, loop: true }
```

Options:
- **`speed`**: playback speed multiplier (default `1`)
- **`loop`**: restart when animation completes (default `false`)
- **`playing`**: pause/resume (default `true`)
- **`catchUp`**: speed up when buffered text is ahead (for streaming)

### Controlled

You provide the current time value directly (useful for syncing with external state):

```ts
time: 2.5 // seconds
// or
time: { mode: 'controlled', value: 2.5 }
```

### CSS

Animation is driven purely by CSS (best performance, no JavaScript animation loop):

```ts
time: 'css'
// or
time: { mode: 'css' }
```

## Effects

All frameworks accept the same effects configuration:

```ts
effects: {
  glow: { radius: 8, color: '#00ccff' },
  wobble: { amplitude: 1.5, frequency: 8 },
  pressureWidth: { strength: 1 },
  taper: { startLength: 0.15, endLength: 0.15 },
  strokeGradient: { colors: 'rainbow' },
}
```

Effects can also be set to `true` for defaults: `{ pressureWidth: true }`.

## Streaming text

For chat-like interfaces where text arrives incrementally, see [Streaming Text](https://tegaki.ink/guides/streaming/).
