Section
AI Chat Interface — Neo-Brutalism
Brutalist AI chat surface with hard black borders, offset drop shadows, flat bright accents, a typing indicator, prompt suggestion chips, and a wired input bar. Press-down hover states and monospace labels give it a raw, editorial character.
- Section
- Tailwind
- HTML
- MIT
Preview
Live section
9:41 100%
devsnips.dev/library/tailwind/sections/ai-product/ai-chat-interface/neo-brutalism/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Sections/AI-Product/ai-chat-interface/neo-brutalism Tailwind/Sections/AI-Product/ai-chat-interface/neo-brutalism <!--
Snippet Name: AI Chat Interface — Neo-Brutalism
Description: Hard-bordered chat panel with offset shadows, a streaming reply, prompt suggestions, and a brutalist input bar.
Author: DevSnips Contributors
Usage Example: Drop into any app shell as an AI assistant surface. The prompt chips and input bar are fully wired in preview.html.
-->
<div class="relative w-full max-w-3xl" data-chat="nb">
<!-- Panel -->
<div class="border-2 border-black bg-white shadow-[8px_8px_0_0_#000]">
<!-- Header -->
<div class="flex items-center justify-between gap-3 border-b-2 border-black bg-[#FFE600] px-5 py-4">
<div class="flex items-center gap-3">
<div class="flex h-11 w-11 items-center justify-center border-2 border-black bg-white text-black shadow-[3px_3px_0_0_#000]">
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true">
<rect x="4" y="7" width="16" height="13" rx="0" />
<path d="M9 7V4h6v3" />
<circle cx="9" cy="13" r="1.2" fill="currentColor" stroke="none" />
<circle cx="15" cy="13" r="1.2" fill="currentColor" stroke="none" />
<path d="M2 12v4M22 12v4" />
</svg>
</div>
<div>
<p class="font-archivo text-base font-extrabold uppercase leading-none tracking-tight">DevSnips Bot</p>
<p class="mt-1 font-mono text-[11px] font-bold uppercase tracking-wider text-black/70">
<span class="inline-block h-2 w-2 border border-black bg-[#00E676]"></span>
ONLINE · GPT-SNIP
</p>
</div>
</div>
<div class="flex items-center gap-2">
<button type="button" class="border-2 border-black bg-white px-2.5 py-2 font-mono text-[11px] font-bold uppercase shadow-[3px_3px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[1px_1px_0_0_#000] focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">HISTORY</button>
<button type="button" aria-label="New chat" class="flex h-9 w-9 items-center justify-center border-2 border-black bg-white shadow-[3px_3px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[1px_1px_0_0_#000] focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><path d="M12 5v14M5 12h14" /></svg>
</button>
</div>
</div>
<!-- Messages -->
<div class="chat-scroll max-h-[420px] min-h-[320px] space-y-5 overflow-y-auto bg-[#FFFDF5] px-5 py-6" data-chat-messages>
<!-- User -->
<div class="flex justify-end">
<div class="max-w-[78%] border-2 border-black bg-[#FF4FA3] px-4 py-3 text-white shadow-[4px_4px_0_0_#000]">
<p class="font-mono text-[10px] font-bold uppercase tracking-wider text-white/80">YOU</p>
<p class="mt-1 font-archivo text-[15px] font-bold leading-snug">How do I animate an accordion with the grid-rows trick?</p>
</div>
</div>
<!-- Assistant -->
<div class="flex justify-start">
<div class="max-w-[80%] border-2 border-black bg-white px-4 py-3 shadow-[4px_4px_0_0_#000]">
<p class="font-mono text-[10px] font-bold uppercase tracking-wider text-black/70">BOT</p>
<p class="mt-1 font-archivo text-[15px] font-medium leading-relaxed text-black">
Wrap your panel in a grid with <code class="border border-black bg-[#FFE600] px-1 font-mono text-[13px] font-bold">grid-rows-[0fr]</code>, animate to <code class="border border-black bg-[#FFE600] px-1 font-mono text-[13px] font-bold">grid-rows-[1fr]</code> over <code class="border border-black bg-[#FFE600] px-1 font-mono text-[13px] font-bold">transition-[grid-template-rows]</code>, and keep an inner <code class="border border-black bg-[#FFE600] px-1 font-mono text-[13px] font-bold">overflow-hidden</code> wrapper. The row grows from 0 to auto smoothly.
</p>
</div>
</div>
<!-- Typing -->
<div class="flex justify-start">
<div class="flex items-center gap-1.5 border-2 border-black bg-white px-4 py-3 shadow-[4px_4px_0_0_#000]" data-chat-typing>
<span class="h-2.5 w-2.5 border border-black bg-[#00E676]"></span>
<span class="h-2.5 w-2.5 border border-black bg-[#FFE600]" style="animation:nb-blink 1.2s infinite .2s"></span>
<span class="h-2.5 w-2.5 border border-black bg-[#FF4FA3]" style="animation:nb-blink 1.2s infinite .4s"></span>
<span class="ml-1 font-mono text-[11px] font-bold uppercase tracking-wider text-black/60">thinking…</span>
</div>
</div>
</div>
<!-- Prompt suggestions -->
<div class="flex flex-wrap gap-2 border-t-2 border-black bg-[#FFFDF5] px-5 py-3">
<button type="button" class="chat-prompt border-2 border-black bg-white px-3 py-1.5 font-mono text-[11px] font-bold uppercase shadow-[2px_2px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">Explain CSS grid</button>
<button type="button" class="chat-prompt border-2 border-black bg-[#00E676] px-3 py-1.5 font-mono text-[11px] font-bold uppercase shadow-[2px_2px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">Build a toast</button>
<button type="button" class="chat-prompt border-2 border-black bg-[#00C2FF] px-3 py-1.5 font-mono text-[11px] font-bold uppercase shadow-[2px_2px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">Refactor my code</button>
</div>
<!-- Input -->
<form class="flex items-center gap-2 border-t-2 border-black bg-white px-5 py-4" data-chat-form>
<div class="relative flex-1">
<input
type="text"
name="prompt"
placeholder="Ask anything…"
aria-label="Message DevSnips Bot"
class="w-full border-2 border-black bg-[#FFFDF5] px-4 py-3 font-archivo text-[15px] font-medium placeholder:text-black/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2"
/>
</div>
<button type="submit" class="flex shrink-0 items-center gap-2 border-2 border-black bg-black px-5 py-3 font-archivo text-sm font-extrabold uppercase tracking-tight text-white shadow-[4px_4px_0_0_#FFE600] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[1px_1px_0_0_#FFE600] focus:outline-none focus-visible:ring-2 focus-visible:ring-[#FFE600] focus-visible:ring-offset-2">
SEND
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
</button>
</form>
</div>
<style>
@keyframes nb-blink { 0%, 60%, 100% { opacity: 1; } 30% { opacity: .25; } }
[data-chat] .chat-scroll::-webkit-scrollbar { width: 10px; }
[data-chat] .chat-scroll::-webkit-scrollbar-track { background: #FFFDF5; border-left: 2px solid #000; }
[data-chat] .chat-scroll::-webkit-scrollbar-thumb { background: #000; border: 2px solid #FFFDF5; }
[data-chat] .chat-scroll { scrollbar-width: thin; scrollbar-color: #000 #FFFDF5; }
</style>
<script>
(function () {
var root = document.currentScript.closest('[data-chat]');
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-[78%] border-2 border-black bg-[#FF4FA3] px-4 py-3 text-white shadow-[4px_4px_0_0_#000]"><p class="font-mono text-[10px] font-bold uppercase tracking-wider text-white/80">YOU</p><p class="mt-1 font-archivo text-[15px] font-bold leading-snug"></p></div>';
row.querySelector('p:last-child').textContent = text;
list.appendChild(row);
list.scrollTop = list.scrollHeight;
}
function addBot(html) {
var row = document.createElement('div');
row.className = 'flex justify-start';
row.innerHTML = '<div class="max-w-[80%] border-2 border-black bg-white px-4 py-3 shadow-[4px_4px_0_0_#000]"><p class="font-mono text-[10px] font-bold uppercase tracking-wider text-black/70">BOT</p><p class="mt-1 font-archivo text-[15px] font-medium leading-relaxed text-black"></p></div>';
row.querySelector('p:last-child').innerHTML = html;
list.appendChild(row);
list.scrollTop = list.scrollHeight;
}
var responses = [
'Great question. Use the grid-rows-[0fr] → [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.',
'I would 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> 159 lines UTF-8 · LF · Spaces: 2
Continue browsing