Section

AI Chat Interface — Vercel

Refined dark monochrome AI chat surface with hairline borders, a subtle conic glow, a glowing ready-state dot, a streaming typing indicator, prompt chips, and a minimal input bar. Generous spacing and a single teal accent echo a premium dev-tool aesthetic.

  • Section
  • Tailwind
  • HTML
  • MIT

Preview

Live section

Interactive preview
Open preview
9:41 100%
devsnips.dev/library/tailwind/sections/ai-product/ai-chat-interface/vercel/
fluid · no fixed width 100%
Dependencies: Tailwind CSS (CDN) · Google Fonts: Geist, Geist Mono Responsive · Keyboard-ready

Install

Add to your project

terminal
npx devsnips add Tailwind/Sections/AI-Product/ai-chat-interface/vercel
registry path: Tailwind/Sections/AI-Product/ai-chat-interface/vercel

Source

Implementation

code.html
<!--
Snippet Name: AI Chat Interface — Vercel
Description: Refined dark monochrome chat panel with a subtle conic glow, hairline borders, a streaming reply, prompt suggestions, and a minimal input bar.
Author: DevSnips Contributors
Usage Example: Drop into a dark product shell as an AI assistant surface. Prompt chips and input bar are fully wired in preview.html.
-->
<div class="relative w-full max-w-2xl" data-chat="vc">

  <!-- Conic glow backdrop -->
  <div class="pointer-events-none absolute -inset-px -z-10 rounded-[14px] opacity-60 [background:radial-gradient(60%_60%_at_50%_0%,rgba(255,255,255,0.10),transparent_70%)]" aria-hidden="true"></div>

  <!-- Panel -->
  <div class="overflow-hidden rounded-[14px] border border-white/10 bg-[#0a0a0a] shadow-[0_0_0_1px_rgba(255,255,255,0.02),0_20px_60px_-20px_rgba(0,0,0,0.9)]">

    <!-- Header -->
    <div class="flex items-center justify-between gap-3 border-b border-white/[0.07] px-5 py-4">
      <div class="flex items-center gap-3">
        <div class="flex h-9 w-9 items-center justify-center rounded-lg border border-white/10 bg-white text-black">
          <svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2 2 19h20L12 2z"/></svg>
        </div>
        <div class="leading-tight">
          <p class="font-g text-[13px] font-medium text-white">DevSnips Assistant</p>
          <p class="vc-mono mt-0.5 text-[11px] text-white/40">
            <span class="vc-dot"></span> Ready · v2
          </p>
        </div>
      </div>
      <div class="flex items-center gap-1.5">
        <button type="button" class="vc-mono hidden rounded-md px-2.5 py-1.5 text-[11px] text-white/50 transition-colors hover:bg-white/[0.06] hover:text-white sm:block focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">History</button>
        <button type="button" aria-label="New chat" class="flex h-8 w-8 items-center justify-center rounded-md text-white/50 transition-colors hover:bg-white/[0.06] hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">
          <svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 5v14M5 12h14" /></svg>
        </button>
      </div>
    </div>

    <!-- Messages -->
    <div class="chat-scroll max-h-[440px] min-h-[340px] space-y-6 overflow-y-auto px-5 py-6" data-chat-messages>
      <!-- User -->
      <div class="flex justify-end">
        <div class="max-w-[80%] rounded-2xl rounded-br-md border border-white/10 bg-white/[0.06] px-4 py-2.5">
          <p class="vc-mono mb-1 text-[10px] uppercase tracking-wider text-white/35">You</p>
          <p class="font-g text-[14px] leading-relaxed text-white/90">How do I animate an accordion with the grid-rows trick?</p>
        </div>
      </div>
      <!-- Assistant -->
      <div class="flex justify-start gap-3">
        <div class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white text-black">
          <svg class="h-3 w-3" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2 2 19h20L12 2z"/></svg>
        </div>
        <div class="max-w-[82%] rounded-2xl rounded-tl-md border border-white/[0.07] bg-transparent px-4 py-2.5">
          <p class="vc-mono mb-1 text-[10px] uppercase tracking-wider text-white/35">Assistant</p>
          <p class="font-g text-[14px] leading-relaxed text-white/75">
            Wrap the panel in <code class="vc-code">grid-rows-[0fr]</code>, animate to <code class="vc-code">grid-rows-[1fr]</code> with <code class="vc-code">transition-[grid-template-rows]</code>, and nest an <code class="vc-code">overflow-hidden</code> wrapper. The row grows from 0 to auto with zero layout cost.
          </p>
        </div>
      </div>
      <!-- Typing -->
      <div class="flex justify-start gap-3" data-chat-typing>
        <div class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white text-black">
          <svg class="h-3 w-3" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2 2 19h20L12 2z"/></svg>
        </div>
        <div class="flex items-center gap-1.5 rounded-2xl rounded-tl-md border border-white/[0.07] px-4 py-3">
          <span class="vc-typing-dot"></span>
          <span class="vc-typing-dot" style="animation-delay:.15s"></span>
          <span class="vc-typing-dot" style="animation-delay:.3s"></span>
        </div>
      </div>
    </div>

    <!-- Prompt suggestions -->
    <div class="flex flex-wrap gap-2 border-t border-white/[0.07] px-5 py-3">
      <button type="button" class="chat-prompt vc-mono rounded-full border border-white/10 bg-white/[0.03] px-3 py-1.5 text-[11px] text-white/60 transition-colors hover:border-white/20 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">Explain CSS grid</button>
      <button type="button" class="chat-prompt vc-mono rounded-full border border-white/10 bg-white/[0.03] px-3 py-1.5 text-[11px] text-white/60 transition-colors hover:border-white/20 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">Build a toast</button>
      <button type="button" class="chat-prompt vc-mono rounded-full border border-white/10 bg-white/[0.03] px-3 py-1.5 text-[11px] text-white/60 transition-colors hover:border-white/20 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30">Refactor my code</button>
    </div>

    <!-- Input -->
    <form class="flex items-center gap-2 border-t border-white/[0.07] px-5 py-4" data-chat-form>
      <div class="relative flex-1">
        <input
          type="text"
          name="prompt"
          placeholder="Ask anything…"
          aria-label="Message DevSnips Assistant"
          class="w-full rounded-lg border border-white/10 bg-white/[0.03] px-4 py-2.5 font-g text-[14px] text-white placeholder:text-white/30 focus:border-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/20"
        />
      </div>
      <button type="submit" class="flex shrink-0 items-center gap-2 rounded-lg border border-white/10 bg-white px-4 py-2.5 font-g text-[13px] font-medium text-black transition-colors hover:bg-white/90 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/40">
        Send
        <svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
      </button>
    </form>
  </div>

  <style>
    [data-chat="vc"] .vc-mono { font-family: 'Geist Mono', ui-monospace, monospace; }
    [data-chat="vc"] .font-g { font-family: 'Geist', sans-serif; }
    [data-chat="vc"] .vc-code { font-family: 'Geist Mono', monospace; font-size: 12px; background: rgba(255,255,255,0.06); padding: 1px 5px; border-radius: 4px; color: rgba(255,255,255,0.9); }
    [data-chat="vc"] .vc-dot { display: inline-block; height: 6px; width: 6px; border-radius: 9999px; background: #50e3c2; margin-right: 5px; box-shadow: 0 0 8px #50e3c2; vertical-align: middle; }
    [data-chat="vc"] .vc-typing-dot { height: 6px; width: 6px; border-radius: 9999px; background: rgba(255,255,255,0.5); animation: vc-bounce 1.2s infinite ease-in-out; }
    @keyframes vc-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-4px); opacity: 1; } }
    [data-chat="vc"] .chat-scroll::-webkit-scrollbar { width: 6px; }
    [data-chat="vc"] .chat-scroll::-webkit-scrollbar-track { background: transparent; }
    [data-chat="vc"] .chat-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 9999px; }
    [data-chat="vc"] .chat-scroll { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.15) transparent; }
  </style>

  <script>
    (function () {
      var root = document.currentScript.closest('[data-chat="vc"]');
      if (!root) return;
      var form = root.querySelector('[data-chat-form]');
      var list = root.querySelector('[data-chat-messages]');
      var input = form && form.querySelector('input[name="prompt"]');
      var typing = root.querySelector('[data-chat-typing]');
      if (!form || !list || !input) return;

      function addUser(text) {
        if (!text.trim()) return;
        var row = document.createElement('div');
        row.className = 'flex justify-end';
        row.innerHTML = '<div class="max-w-[80%] rounded-2xl rounded-br-md border border-white/10 bg-white/[0.06] px-4 py-2.5"><p class="vc-mono mb-1 text-[10px] uppercase tracking-wider text-white/35">You</p><p class="font-g text-[14px] leading-relaxed text-white/90"></p></div>';
        row.querySelector('p:last-child').textContent = text;
        list.appendChild(row);
        list.scrollTop = list.scrollHeight;
      }

      function addBot(text) {
        var row = document.createElement('div');
        row.className = 'flex justify-start gap-3';
        row.innerHTML = '<div class="mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-white text-black"><svg class="h-3 w-3" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2 2 19h20L12 2z"/></svg></div><div class="max-w-[82%] rounded-2xl rounded-tl-md border border-white/[0.07] bg-transparent px-4 py-2.5"><p class="vc-mono mb-1 text-[10px] uppercase tracking-wider text-white/35">Assistant</p><p class="font-g text-[14px] leading-relaxed text-white/75"></p></div>';
        row.querySelector('p:last-child').textContent = text;
        list.appendChild(row);
        list.scrollTop = list.scrollHeight;
      }

      var responses = [
        'Use the grid-rows-[0fr] to [1fr] trick wrapped in overflow-hidden for buttery height animation.',
        'Try a single-open mode: close sibling items on open and toggle aria-expanded on the trigger.',
        'Reach for focus-visible:ring utilities plus role="region" and aria-labelledby for accessibility.',
        'Drop the snippet into a docs layout — each item toggles independently with no extra wiring.'
      ];
      var i = 0;

      function reply(text) {
        addUser(text);
        if (typing) { typing.style.display = 'flex'; list.scrollTop = list.scrollHeight; }
        setTimeout(function () {
          if (typing) typing.style.display = 'none';
          addBot(responses[i % responses.length]); i++;
        }, 1100);
      }

      form.addEventListener('submit', function (e) {
        e.preventDefault();
        reply(input.value);
        input.value = '';
      });

      root.querySelectorAll('.chat-prompt').forEach(function (chip) {
        chip.addEventListener('click', function () { reply(chip.textContent.trim()); });
      });
    })();
  </script>
</div>
165 lines UTF-8 · LF · Spaces: 2

AI-ready

Available to your agent.

This section is reachable through the DevSnips CLI, MCP server and Skills integrations — one registry, one resource path.

Resource path

devsnips://sections/ai-product/ai-chat-interface/vercel

Continue browsing

View all