Streaming Text
A copy-paste ai / chat ui component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
AI / Chat UIHTMLCSSJavaScriptany framework
Generating a response
Copy into your project
HTML
<!-- Streaming Text — append tokens to the <p> as your stream arrives -->
<div class="nuda-stream-text">
<p>Generating a response<span class="nuda-stream-text__cursor"></span></p>
</div>CSS
/* Streaming Text
Token-stream feel: text "types" left-to-right with a blinking caret.
Customize: --st-cursor, --st-bg, the steps(N) value. */
.nuda-stream-text {
--st-cursor: #e4ff54;
--st-bg: rgba(255, 255, 255, 0.03);
padding: 10px 14px;
background: var(--st-bg);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
max-width: 100%;
}
.nuda-stream-text p {
margin: 0;
font: 500 0.875rem ui-sans-serif, system-ui, sans-serif;
color: #fafafa;
line-height: 1.5;
overflow: hidden;
white-space: nowrap;
/* If you stream from JS, drop this animation and just append text. */
animation: nuda-st-type 4s steps(28) infinite;
}
.nuda-stream-text__cursor {
display: inline-block;
width: 1.5px;
height: 1em;
background: var(--st-cursor);
margin-left: 2px;
vertical-align: middle;
animation: nuda-st-blink 1s steps(2) infinite;
}
@keyframes nuda-st-type {
0% { width: 0; }
80%, 100% { width: 100%; }
}
@keyframes nuda-st-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
.nuda-stream-text p,
.nuda-stream-text__cursor { animation: none; }
}JavaScript
/* Streaming Text — append tokens from a real stream.
Drop the CSS typing animation when using this. */
(function () {
var p = document.querySelector('.nuda-stream-text p');
var cursor = document.querySelector('.nuda-stream-text__cursor');
if (!p) return;
// Example: typing simulation. Replace with your fetch/SSE/WebSocket reader.
var text = 'Streaming a response token by token…';
p.textContent = '';
if (cursor) p.appendChild(cursor);
var i = 0;
var iv = setInterval(function () {
if (i >= text.length) return clearInterval(iv);
p.insertBefore(document.createTextNode(text[i++]), cursor || null);
}, 28);
})();How to use Streaming Text
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.