Section
Agent Workflow — Vercel
Refined dark monochrome agent execution stepper visualizing Plan, Search, Reason, Act, Reflect, Respond. Hairline borders, generous spacing, and a single teal accent color each step by status. A Run button drives steps through pending → running → done on a timer with a glowing filling progress bar and a live log line. Respects prefers-reduced-motion.
- Section
- Tailwind
- HTML
- MIT
Preview
Live section
9:41 100%
devsnips.dev/library/tailwind/sections/ai-product/agent-workflow/vercel/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Sections/AI-Product/agent-workflow/vercel Tailwind/Sections/AI-Product/agent-workflow/vercel <!--
Snippet Name: Agent Workflow — Vercel
Description: Dark monochrome agent execution stepper that animates Plan → Search → Reason → Act → Reflect → Respond through pending/running/done states with a teal-accented filling connector and a Run button.
Author: DevSnips Contributors
Usage Example: Drop into a dark product shell as an agent run visualization. The Run button drives the steps through statuses on a timer.
-->
<div class="relative w-full max-w-2xl" data-workflow="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 flex-wrap 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="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<circle cx="6" cy="6" r="2.4" /><circle cx="18" cy="6" r="2.4" /><circle cx="12" cy="18" r="2.4" />
<path d="M7.6 7.6 10.6 16M16.4 7.6 13.4 16" />
</svg>
</div>
<div class="leading-tight">
<p class="font-g text-[13px] font-medium text-white">Agent Run · #4827</p>
<p class="vc-mono mt-0.5 text-[11px] text-white/40">
<span class="wf-status-dot vc-dot"></span> <span data-wf-status-label>Idle · 6 steps</span>
</p>
</div>
</div>
<button type="button" data-wf-run class="flex items-center gap-2 rounded-lg border border-white/10 bg-white px-4 py-2 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">
<svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M6 4l14 8-14 8V4z" /></svg>
<span data-wf-run-label>Run</span>
</button>
</div>
<!-- Progress bar -->
<div class="border-b border-white/[0.07] px-5 py-4">
<div class="flex items-center justify-between">
<p class="vc-mono text-[11px] text-white/40">Progress</p>
<p class="vc-mono text-[11px] text-white/70" data-wf-count>0 / 6</p>
</div>
<div class="mt-2 h-1.5 w-full overflow-hidden rounded-full bg-white/[0.06]">
<div class="wf-progress h-full w-0 rounded-full bg-[#50e3c2] transition-[width] duration-300 ease-out" style="box-shadow:0 0 8px #50e3c2" data-wf-progress></div>
</div>
</div>
<!-- Steps -->
<ol class="wf-steps divide-y divide-white/[0.06]" data-wf-steps>
<!-- steps injected by JS -->
</ol>
<!-- Footer / log -->
<div class="border-t border-white/[0.07] px-5 py-3">
<p class="vc-mono text-[11px] text-white/40">
<span class="text-[#50e3c2]">$</span> <span data-wf-log>Awaiting start.</span>
</p>
</div>
</div>
<style>
[data-workflow="vc"] .vc-mono { font-family: 'Geist Mono', ui-monospace, monospace; }
[data-workflow="vc"] .font-g { font-family: 'Geist', sans-serif; }
[data-workflow="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-workflow="vc"] .wf-step { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 14px; padding: 14px 20px; }
[data-workflow="vc"] .wf-node { display: flex; align-items: center; justify-content: center; height: 36px; width: 36px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.1); background: rgba(255,255,255,0.03); color: rgba(255,255,255,0.5); transition: all .25s ease; }
[data-workflow="vc"] .wf-step[data-status="done"] .wf-node { background: #50e3c2; color: #000; border-color: #50e3c2; }
[data-workflow="vc"] .wf-step[data-status="running"] .wf-node { background: rgba(80,227,194,0.12); color: #50e3c2; border-color: rgba(80,227,194,0.5); animation: vc-pulse 1.4s infinite ease-in-out; }
@keyframes vc-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(80,227,194,0); } 50% { box-shadow: 0 0 0 4px rgba(80,227,194,0.15); } }
[data-workflow="vc"] .wf-step[data-status="done"] .wf-title { color: rgba(255,255,255,0.9); }
[data-workflow="vc"] .wf-step[data-status="running"] .wf-title { color: #fff; }
[data-workflow="vc"] .wf-step[data-status="pending"] .wf-title { color: rgba(255,255,255,0.4); }
[data-workflow="vc"] .wf-pill { font-family: 'Geist Mono', monospace; font-size: 10px; text-transform: uppercase; letter-spacing: .08em; padding: 2px 8px; border-radius: 9999px; border: 1px solid rgba(255,255,255,0.1); color: rgba(255,255,255,0.5); }
[data-workflow="vc"] .wf-step[data-status="done"] .wf-pill { color: #50e3c2; border-color: rgba(80,227,194,0.4); }
[data-workflow="vc"] .wf-step[data-status="running"] .wf-pill { color: #50e3c2; border-color: rgba(80,227,194,0.5); background: rgba(80,227,194,0.08); }
</style>
<script>
(function () {
var root = document.currentScript.closest('[data-workflow="vc"]');
if (!root) return;
var STEPS = [
{ id: 'plan', label: 'Plan', detail: 'Decompose goal into subtasks', icon: '<path d="M9 4h6a2 2 0 0 1 2 2v3M9 20h6a2 2 0 0 0 2-2v-3"/><rect x="4" y="8" width="6" height="5"/><path d="M10 10.5h4"/>' },
{ id: 'search', label: 'Search', detail: 'Retrieve context from tools', icon: '<circle cx="11" cy="11" r="6"/><path d="M20 20l-4-4"/>' },
{ id: 'reason', label: 'Reason', detail: 'Chain logic over evidence', icon: '<path d="M12 3v3M12 18v3M3 12h3M18 12h3"/><circle cx="12" cy="12" r="3.4"/>' },
{ id: 'act', label: 'Act', detail: 'Call tool: write_file()', icon: '<path d="M4 12h11M11 8l4 4-4 4"/><rect x="16" y="6" width="4" height="12"/>' },
{ id: 'reflect', label: 'Reflect', detail: 'Verify output vs goal', icon: '<path d="M4 6h16M4 12h10M4 18h7"/>' },
{ id: 'respond', label: 'Respond', detail: 'Stream final answer', icon: '<path d="M4 5h16v10H7l-3 3V5z"/>' }
];
var ol = root.querySelector('[data-wf-steps]');
var progress = root.querySelector('[data-wf-progress]');
var countEl = root.querySelector('[data-wf-count]');
var runBtn = root.querySelector('[data-wf-run]');
var runLabel = root.querySelector('[data-wf-run-label]');
var statusLabel = root.querySelector('[data-wf-status-label]');
var logEl = root.querySelector('[data-wf-log]');
var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var tickMs = reduceMotion ? 0 : 1100;
STEPS.forEach(function (s, idx) {
var li = document.createElement('li');
li.className = 'wf-step';
li.setAttribute('data-step', s.id);
li.setAttribute('data-status', 'pending');
li.setAttribute('aria-label', 'Step ' + (idx + 1) + ' of ' + STEPS.length + ': ' + s.label + ', pending');
li.innerHTML =
'<div class="wf-node">' +
'<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">' + s.icon + '</svg>' +
'</div>' +
'<div>' +
'<p class="wf-title font-g text-[14px] font-medium leading-tight">' + s.label + '</p>' +
'<p class="vc-mono mt-0.5 text-[11px] text-white/35">' + s.detail + '</p>' +
'</div>' +
'<span class="wf-pill">Pending</span>';
ol.appendChild(li);
});
var stepEls = Array.prototype.slice.call(ol.querySelectorAll('.wf-step'));
var running = false;
var timer = null;
function setStatus(el, status) {
el.setAttribute('data-status', status);
var idx = stepEls.indexOf(el);
el.setAttribute('aria-label', 'Step ' + (idx + 1) + ' of ' + STEPS.length + ': ' + STEPS[idx].label + ', ' + status);
var pill = el.querySelector('.wf-pill');
var label = status.charAt(0).toUpperCase() + status.slice(1);
pill.textContent = label;
}
function renderProgress(done) {
var pct = (done / STEPS.length) * 100;
progress.style.width = pct + '%';
countEl.textContent = done + ' / ' + STEPS.length;
}
function setHeaderState(state) {
var map = {
idle: 'Idle · 6 steps',
running: 'Running…',
done: 'Completed'
};
if (statusLabel) statusLabel.textContent = map[state] || map.idle;
}
function reset() {
stepEls.forEach(function (el) { setStatus(el, 'pending'); });
renderProgress(0);
setHeaderState('idle');
if (logEl) logEl.textContent = 'Awaiting start.';
}
function finish() {
running = false;
setHeaderState('done');
if (runBtn) { runBtn.disabled = false; if (runLabel) runLabel.textContent = 'Run again'; }
if (logEl) logEl.textContent = 'Run complete. 6/6 steps succeeded.';
}
function run() {
if (running) return;
running = true;
if (runBtn) runBtn.disabled = true;
if (runLabel) runLabel.textContent = 'Running';
reset();
setHeaderState('running');
if (logEl) logEl.textContent = 'Starting agent run…';
var i = 0;
function next() {
if (i > 0) {
setStatus(stepEls[i - 1], 'done');
if (logEl) logEl.textContent = 'Completed: ' + STEPS[i - 1].label;
renderProgress(i);
}
if (i >= STEPS.length) { finish(); return; }
setStatus(stepEls[i], 'running');
if (logEl) logEl.textContent = 'Executing: ' + STEPS[i].label;
i++;
if (tickMs === 0) { next(); }
else { timer = setTimeout(next, tickMs); }
}
next();
}
if (runBtn) runBtn.addEventListener('click', function () { if (timer) clearTimeout(timer); run(); });
reset();
})();
</script>
</div> 193 lines UTF-8 · LF · Spaces: 2
Continue browsing