Skip to content

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.

More ai / chat ui components

← Browse all NudaUI components