Section
Code Playground — Neo-Brutalism
Brutalist code playground with hard black borders, offset drop shadows, and flat bright accents. A tabbed editor pane (HTML/JS/CSS) with line numbers sits beside a live sandboxed iframe output, plus a wired Run button and reset control.
- Section
- Tailwind
- HTML
- MIT
Preview
Live section
9:41 100%
devsnips.dev/library/tailwind/sections/developer/code-playground/neo-brutalism/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Sections/Developer/code-playground/neo-brutalism Tailwind/Sections/Developer/code-playground/neo-brutalism <!--
Snippet Name: Code Playground — Neo-Brutalism
Description: Hard-bordered code editor + live output playground with a file tab switcher, line numbers, and a wired Run button.
Author: DevSnips Contributors
Usage Example: Drop into any app shell as a live code editor surface. The Run button renders the HTML tab into the output iframe; tabs switch files.
-->
<div class="relative w-full max-w-5xl" data-playground="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">
<path d="M8 9l-3 3 3 3M16 9l3 3-3 3M13 6l-2 12" />
</svg>
</div>
<div>
<p class="font-archivo text-base font-extrabold uppercase leading-none tracking-tight">Playground</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>
LIVE · sandbox.html
</p>
</div>
</div>
<div class="flex items-center gap-2">
<button type="button" aria-label="Reset code" class="pg-reset 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="M3 12a9 9 0 1 0 3-6.7M3 4v4h4" /></svg>
</button>
<button type="button" class="pg-run flex shrink-0 items-center gap-2 border-2 border-black bg-black px-5 py-2.5 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">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M6 4l14 8-14 8z" /></svg>
RUN
</button>
</div>
</div>
<!-- File tabs -->
<div class="flex items-stretch border-b-2 border-black bg-[#FFFDF5]" role="tablist" aria-label="Editor files">
<button type="button" role="tab" aria-selected="true" data-tab="html" class="pg-tab border-r-2 border-black bg-white px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider text-black transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset">
<span class="inline-block h-2.5 w-2.5 border border-black bg-[#FF4FA3] align-middle"></span>
index.html
</button>
<button type="button" role="tab" aria-selected="false" data-tab="js" class="pg-tab border-r-2 border-black bg-[#FFFDF5] px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider text-black/60 transition-colors hover:bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset">
<span class="inline-block h-2.5 w-2.5 border border-black bg-[#00C2FF] align-middle"></span>
app.js
</button>
<button type="button" role="tab" aria-selected="false" data-tab="css" class="pg-tab border-r-2 border-black bg-[#FFFDF5] px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider text-black/60 transition-colors hover:bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset">
<span class="inline-block h-2.5 w-2.5 border border-black bg-[#00E676] align-middle"></span>
styles.css
</button>
<span class="ml-auto self-center pr-4 font-mono text-[10px] font-bold uppercase tracking-wider text-black/40">UTF-8 · LF</span>
</div>
<!-- Editor + Output -->
<div class="grid grid-cols-1 lg:grid-cols-2">
<!-- Editor -->
<div class="border-b-2 border-black lg:border-b-0 lg:border-r-2">
<div class="flex items-center justify-between border-b-2 border-black bg-white px-4 py-2">
<p class="font-mono text-[10px] font-bold uppercase tracking-wider text-black/60">EDITOR</p>
<p class="pg-status font-mono text-[10px] font-bold uppercase tracking-wider text-black/40">READY</p>
</div>
<div class="flex h-[360px] bg-[#FFFDF5]">
<!-- Line numbers -->
<pre class="pg-lines select-none border-r-2 border-black bg-white px-3 py-3 text-right font-mono text-[13px] font-medium leading-[1.5] text-black/40" aria-hidden="true">1
2
3
4
5
6
7
8
9
10
11
12</pre>
<!-- Code area -->
<textarea
class="pg-code w-full resize-none bg-[#FFFDF5] px-4 py-3 font-mono text-[13px] font-medium leading-[1.5] text-black placeholder:text-black/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset"
spellcheck="false"
autocomplete="off"
autocapitalize="off"
aria-label="Code editor"
data-lang="html"
></textarea>
</div>
</div>
<!-- Output -->
<div>
<div class="flex items-center justify-between border-b-2 border-black bg-[#00E676] px-4 py-2">
<p class="font-mono text-[10px] font-bold uppercase tracking-wider text-black">OUTPUT</p>
<p class="pg-render-time font-mono text-[10px] font-bold uppercase tracking-wider text-black/60">— ms</p>
</div>
<div class="h-[360px] bg-white p-2">
<iframe
title="Rendered output"
class="pg-output h-full w-full border-2 border-black bg-white"
sandbox="allow-scripts"
srcdoc="<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{font-family:system-ui,sans-serif;padding:16px;margin:0;color:#111}</style></head><body><p style="opacity:.5">Press <b>RUN</b> to render.</p></body></html>"
></iframe>
</div>
</div>
</div>
<!-- Footer / status -->
<div class="flex flex-wrap items-center justify-between gap-2 border-t-2 border-black bg-white px-5 py-3">
<p class="font-mono text-[11px] font-bold uppercase tracking-wider text-black/60">
<span class="pg-count">0</span> CHARS · <span class="pg-lines-count">0</span> LINES
</p>
<p class="font-mono text-[11px] font-bold uppercase tracking-wider text-black/40">RUNTIME: BROWSER SANDBOX</p>
</div>
</div>
<style>
[data-playground="nb"] .pg-code { tab-size: 2; }
[data-playground="nb"] .pg-code::-webkit-scrollbar { width: 10px; height: 10px; }
[data-playground="nb"] .pg-code::-webkit-scrollbar-track { background: #FFFDF5; }
[data-playground="nb"] .pg-code::-webkit-scrollbar-thumb { background: #000; border: 2px solid #FFFDF5; }
[data-playground="nb"] .pg-code { scrollbar-width: thin; scrollbar-color: #000 #FFFDF5; }
</style>
<script>
(function () {
var root = document.currentScript.closest('[data-playground="nb"]');
if (!root) return;
var files = {
html: '<div class="card">\n <h1>Hello, DevSnips</h1>\n <p>Edit the HTML, then hit RUN.</p>\n <button onclick="bump()">Clicked 0 times</button>\n</div>',
js: 'var n = 0;\nfunction bump() {\n n += 1;\n var b = document.querySelector("button");\n b.textContent = "Clicked " + n + " times";\n b.style.background = n % 2 ? "#FF4FA3" : "#00C2FF";\n}',
css: '.card {\n font-family: system-ui, sans-serif;\n padding: 24px;\n max-width: 320px;\n border: 2px solid #000;\n box-shadow: 6px 6px 0 #000;\n}\nh1 { margin: 0 0 8px; font-size: 22px; text-transform: uppercase; }\nbutton {\n margin-top: 12px; border: 2px solid #000;\n padding: 8px 14px; font-weight: 800; cursor: pointer;\n}'
};
var codeEl = root.querySelector('.pg-code');
var output = root.querySelector('.pg-output');
var runBtn = root.querySelector('.pg-run');
var resetBtn = root.querySelector('.pg-reset');
var tabs = root.querySelectorAll('.pg-tab');
var status = root.querySelector('.pg-status');
var renderTime = root.querySelector('.pg-render-time');
var countEl = root.querySelector('.pg-count');
var linesCountEl = root.querySelector('.pg-lines-count');
var linesEl = root.querySelector('.pg-lines');
var current = 'html';
function escapeHtml(s) {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
function setLines(n) {
var out = [];
for (var i = 1; i <= Math.max(n, 1); i++) out.push(i);
linesEl.textContent = out.join('\n');
}
function updateStats() {
var v = codeEl.value;
var lines = v.split('\n').length;
countEl.textContent = v.length;
linesCountEl.textContent = lines;
setLines(lines);
}
function load(tab) {
current = tab;
codeEl.value = files[tab];
codeEl.dataset.lang = tab;
updateStats();
tabs.forEach(function (t) {
var on = t.dataset.tab === tab;
t.setAttribute('aria-selected', on ? 'true' : 'false');
t.className = on
? 'pg-tab border-r-2 border-black bg-white px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider text-black transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset'
: 'pg-tab border-r-2 border-black bg-[#FFFDF5] px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider text-black/60 transition-colors hover:bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-inset';
});
}
function run() {
var t0 = performance.now();
var html = files.html;
var css = files.css;
var js = files.js;
if (current === 'html') html = codeEl.value;
if (current === 'css') css = codeEl.value;
if (current === 'js') js = codeEl.value;
var doc = '<!DOCTYPE html><html><head><meta charset="utf-8"><style>' +
escapeHtml(css) + '</style></head><body>' + escapeHtml(html) +
'<' + 'script>' + js + '<' + '/script></body></html>';
output.srcdoc = doc;
var dt = Math.round(performance.now() - t0);
renderTime.textContent = dt + ' ms';
status.textContent = 'RENDERED';
}
runBtn.addEventListener('click', run);
resetBtn.addEventListener('click', function () { load(current); run(); });
tabs.forEach(function (t) {
t.addEventListener('click', function () { load(t.dataset.tab); });
});
codeEl.addEventListener('input', updateStats);
load('html');
run();
})();
</script>
</div> 208 lines UTF-8 · LF · Spaces: 2
Continue browsing