animated-text-presentation
v1.1.2
Published
TikTok-inspired animated text presentation with TypeScript
Readme
Dictee Display Live
A lightweight TypeScript/React library for rendering live, word-by-word dictation
animations (inspired by TikTok-style lyric reveals). It ships both an imperative
API (displayLive) and a React wrapper (<DisplayLive />) so you can embed the
animation in any DOM node or React tree.
Features
- Text playback controller with play/pause/stop/rewind controls
- Style presets (highlight, gradient, typewriter, etc.) plus custom colors
- React hook + component wrapper for idiomatic integration
- Rolldown build that outputs ESM/CJS/IIFE bundles and bundled types
- Storybook playground (Vite-powered) showcasing responsive layouts and styles
Getting Started
# install dependencies (bun, npm, or pnpm)
bun install
# build the library bundles (dist/index.*)
bun run build:lib
# run storybook on http://localhost:6006
bun run storybookStorybook Playground
The legacy index.html harness has been retired in favor of the
Display/DisplayLive/InteractivePlayground story. Fire up Storybook to explore the
full-featured demo (style selector, solo toggle, card theme switcher, speed controls,
and progress HUD) without leaving the docs environment.
React Usage
import 'animated-text-presentation/word-style.css';
import { DisplayLive } from 'animated-text-presentation';
import type { TextData, StyleConfig } from 'animated-text-presentation';
const data: TextData = {
sentence: "On va commencer par notre zone habituelle...",
audioUrl: "/audio/voiceover.wav", // Link to the voice track
/* timings and fragments... */
};
const styleConfig: StyleConfig = {
type: 'highlight',
solo: false,
colors: ['#f97316', '#fde047']
};
const customStyleConfig: StyleConfig = {
type: 'soft-custom',
solo: false,
// [Main Color, Text Color (optional)]
colors: ['#ff0050', '#ffffff']
};
export function Example() {
return (
<DisplayLive
textData={data}
styleConfig={styleConfig}
style={{ width: '400px', minHeight: '120px' }}
/>
);
}Next.js tip: if you're using the App Router, import
animated-text-presentation/word-style.cssinapp/layout.tsx(or_app.tsxfor the pages router) so the animation classes are available globally.
Imperative Usage
import 'animated-text-presentation/word-style.css';
import { displayLive } from 'animated-text-presentation';
const controller = displayLive(textData, 'destination-element-id', styleConfig);
// Listen for playback state changes
controller.on('stateChange', ({ state }) => {
console.log('Current state:', state);
});
controller.play();Customizing Text Size & Typography
All presets now read their font-family, font-size, and font-weight from styleConfig.style. Each type ships with sensible defaults, but you can override any of them on a per-instance basis:
const styleConfig: StyleConfig = {
type: 'tiktok-gradient',
solo: false,
colors: ['#7928ca', '#ff0080', '#ffdd00'],
style: {
fontFamily: "'Space Grotesk', sans-serif",
fontSize: 'clamp(36px, 5vw, 64px)',
fontWeight: '600'
}
};Providing only one property (e.g., fontSize) leaves the other defaults intact, so you can tweak text sizing without restyling the rest of the preset.
Soft Custom Style
The soft-custom style supports dynamic coloring via the colors array:
colors[0]: Main Color (Background/Gradient/Shadow).colors[1]: Text Color (Optional). If omitted, it defaults to Black or White based on contrast.
const style: StyleConfig = {
type: 'soft-custom',
colors: ['#00ff00'] // Text defaults to Black
};Audio Synchronization
The library supports playing an audio track (like a voiceover) in sync with the text animation.
Basic Sync
Simply provide the audioUrl in your TextData object:
const data: TextData = {
sentence: "...",
audioUrl: "path/to/voice.mp3",
wordTimings: [...],
sentenceFragments: {...}
};Audio Effects (StyleConfig)
You can also configure global audio settings and effects (via Tone.js) in your StyleConfig:
const styleConfig: StyleConfig = {
type: 'highlight',
audio: {
source: "optional-override-url.mp3", // Use this if not provided in TextData
volume: 0.8,
reverb: { decay: 2, wet: 0.3 },
pitchShift: { pitch: 2 }
}
};Available effects: reverb, chorus, vibrato, and pitchShift.
Playback States
The controller emits a stateChange event whenever the playback state shifts. This is particularly useful for handling audio/text synchronization:
| State | Description |
| :--- | :--- |
| ready | Initial state before playback begins. |
| playing | Text animation and audio are active. |
| paused | Playback is currently suspended. |
| textEnded | Text animation is complete, but audio is still playing. |
| ended | Both text animation and audio have finished. |
Dynamic Data Processing
If you have raw text and word timings (e.g., from an AI transcription), you can use the buildSentenceFragments utility to generate the required TextData structure:
import { buildSentenceFragments } from 'animated-text-presentation/text';
const rawText = "Hello world, this is a test.";
const wordTimings = [
{ word: "Hello", startTime: 0, endTime: 500 },
{ word: "world", startTime: 600, endTime: 1000 },
// ...
];
const result = buildSentenceFragments(rawText, [], wordTimings);
const textData = {
sentence: rawText,
sentenceFragments: {
fragments: result.fragments,
placeholderCount: result.placeholderCount,
debug: result.debug
},
wordTimings: wordTimings
};Scripts
bun run build– builds the distributable bundles plus shared CSS.bun run build:bundle– Rolldown build (ESM/CJS/IIFE + types).bun run storybook/bun run build-storybook– develop or build docs.
Development Notes
- Source lives under
src/. React helpers are insrc/react/. - Rolldown entry point is
src/index.ts. - Storybook stories live in
src/stories/; config is under.storybook/.
License
MIT © 2025
