use-animated-markdown-content.ts
Jul 8, 2025ยทanimate the rendering of markdown content, usually from an llm
import { useRef } from 'react';
import { animate } from 'framer-motion';
import { marked } from 'marked';
export function useAnimatedMarkdownContent() {
const containerRef = useRef<HTMLElement>(null);
const prevContentRef = useRef<string>('');
const animateContent = (newText: string) => {
return new Promise<void>((resolve) => {
const oldText = prevContentRef.current;
// Fade out old text
animate(oldText.length, 0, {
duration: 0.3,
onUpdate: (latest) => {
if (containerRef.current) {
containerRef.current.innerHTML = marked.parse(
oldText.slice(0, Math.floor(latest))
) as string;
}
},
onComplete: () => {
// Fade in new text
animate(0, newText.length, {
duration: 0.3,
onUpdate: (latest) => {
if (containerRef.current) {
containerRef.current.innerHTML = marked.parse(
newText.slice(0, Math.floor(latest))
) as string;
}
},
onComplete: () => {
prevContentRef.current = newText;
resolve();
},
});
},
});
});
};
const resetContent = () => {
if (containerRef.current) {
containerRef.current.innerHTML = '';
}
prevContentRef.current = '';
};
const renderContent = async (markdown: string) => {
return marked.parse(markdown) as string;
};
const renderContentSync = (markdown: string) => {
return marked.parse(markdown, { async: false }) as string;
};
return {
containerRef,
animateContent,
resetContent,
renderContent,
renderContentSync,
};
}