All Prompts
All Prompts

featurerotatorinteractiveanimateddarkmodernresponsivecarouselsection
Interactive Feature Rotator
Интерактивный ротатор фич: анимированный слайдер с плавной сменой контента и эффектами при наведении. Идеален для демонстрации продуктов.
Prompt
<div class="min-h-screen relative overflow-hidden text-neutral-200 antialiased font-sans" style="font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial;">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
</style>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<div class="pointer-events-none absolute inset-0 bg-[radial-gradient(60%_40%_at_70%_30%,rgba(120,119,198,0.15),transparent_60%)]"></div>
<section class="max-w-7xl mx-auto px-6 md:px-8 py-16 md:py-24">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 items-center">
<div>
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-semibold tracking-tight text-white">
Plan, write, and shipwork that matters
<br class="hidden sm:block">
</h1>
<div id="bulletList" class="mt-10 space-y-5"></div>
</div>
<div class="relative">
<div class="relative rounded-2xl border border-neutral-800/80 bg-neutral-900/50 shadow-[0_10px_60px_-15px_rgba(0,0,0,0.6)] ring-1 ring-white/5 backdrop-blur-md overflow-hidden">
<div class="h-12 flex items-center gap-2 px-4 border-b border-neutral-800/70 text-neutral-400 text-sm">
<i data-lucide="file-text" class="w-4 h-4"></i>
<span class="truncate">Nebula relay</span>
<span class="opacity-50">›</span>
<span class="truncate text-neutral-300">Product brief</span>
<span class="ml-auto flex items-center gap-1 opacity-60">
<i data-lucide="more-horizontal" class="w-4 h-4"></i>
</span>
</div>
<div class="relative px-6 md:px-8 py-8 md:py-10">
<div class="absolute left-3 top-1/2 -translate-y-1/2 flex flex-col gap-1 text-neutral-700">
<span class="w-1 h-1 rounded-full bg-current"></span>
<span class="w-1 h-1 rounded-full bg-current"></span>
<span class="w-1 h-1 rounded-full bg-current"></span>
</div>
<div id="iconBox" class="w-12 h-12 rounded-xl flex items-center justify-center mb-5"></div>
<div class="relative">
<h2 class="text-2xl sm:text-3xl font-semibold tracking-tight text-neutral-100 flex flex-wrap items-center gap-3">
<span id="highlightPill" class="inline-flex items-center rounded-md px-2.5 py-1.5 ring-1 text-base sm:text-lg"></span>
<span id="highlightTail"></span>
</h2>
<div id="badgesLayer" class="relative"></div>
</div>
<p id="bodyCopy" class="mt-5 text-neutral-400 leading-relaxed max-w-prose text-[17px] sm:text-lg"></p>
<div class="mt-8 space-y-2">
<div class="h-3 rounded bg-neutral-800/70 w-2/3"></div>
<div class="h-3 rounded bg-neutral-800/70 w-5/6"></div>
<div class="h-3 rounded bg-neutral-800/70 w-1/2"></div>
</div>
<div class="mt-8 space-y-2 opacity-80">
<div class="h-3 rounded bg-neutral-800/70 w-11/12"></div>
<div class="h-3 rounded bg-neutral-800/70 w-2/3"></div>
<div class="h-3 rounded bg-neutral-800/70 w-3/4"></div>
</div>
<div class="pointer-events-none absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-neutral-950/80 to-transparent"></div>
</div>
</div>
</div>
</div>
</section>
<script>
const slides = [{ key: 'docs', bullet: 'Real‑time briefs', accent: 'emerald', icon: 'users', pillText: 'Co‑create', tailText: 'product briefs', body: 'Draft clear briefs together with multiplayer editing. Structure work with headings, checklists, and callouts.', badges: [{ text: 'noa', color: 'emerald' , target: 'briefs' }, { text: 'leo', color: 'violet' , target: 'checklists' }] }, { key: 'comments', bullet: 'Threaded reviews', accent: 'amber', icon: 'message-square', pillText: 'Review in', tailText: 'context', body: 'Keep decisions attached to the work with inline threads. Mention teammates, resolve quickly, and move forward.', badges: [{ text: 'ivan', color: 'amber', target: 'threads' }, { text: 'sara', color: 'sky', target: 'Mention' }] }, { key: 'commands', bullet: 'Commands to tickets', accent: 'violet', icon: 'workflow', pillText: 'Turn notes into', tailText: 'tickets', body: 'Use quick commands to convert writing into scoped tickets with owners, labels, and estimates.', badges: [{ text: 'jin', color: 'violet', target: 'tickets' }, { text: 'nora', color: 'emerald', target: 'owners' }] }]; const accents = { emerald: { pill: 'ring-emerald-500/60 bg-emerald-500/10 text-emerald-200', iconBox: 'bg-emerald-500/10 text-emerald-400', bar: 'bg-emerald-400', }, amber: { pill: 'ring-amber-500/60 bg-amber-500/10 text-amber-200', iconBox: 'bg-amber-500/10 text-amber-400', bar: 'bg-amber-400', }, violet: { pill: 'ring-violet-500/60 bg-violet-500/10 text-violet-200', iconBox: 'bg-violet-500/10 text-violet-400', bar: 'bg-violet-400', }, sky: { pill: 'ring-sky-500/60 bg-sky-500/10 text-sky-200', iconBox: 'bg-sky-500/10 text-sky-400', bar: 'bg-sky-400', } }; const highlightMap = { docs: ['briefs', 'checklists'], comments: ['threads', 'Mention'], commands: ['tickets', 'owners'] }; const root = document.querySelector('[data-component="feature-rotator"]') || document.querySelector('div'); const bulletList = document.getElementById('bulletList'); const iconBox = document.getElementById('iconBox'); const highlightPill = document.getElementById('highlightPill'); const highlightTail = document.getElementById('highlightTail'); const bodyCopy = document.getElementById('bodyCopy'); const badgesLayer = document.getElementById('badgesLayer'); function renderBullets(active) { bulletList.innerHTML = ''; slides.forEach((s, i) => { const isActive = i === active; const row = document.createElement('button'); row.type = 'button'; row.setAttribute('data-index', i); row.className = 'group w-full flex items-center gap-3 sm:gap-4'; row.innerHTML = `<span class="h-6 w-1 rounded-full ${isActive ? accents[slides[active].accent].bar : 'bg-neutral-700'} transition-colors"></span><span class="text-sm sm:text-base ${isActive ? 'text-white' : 'text-neutral-500 group-hover:text-neutral-300'} font-medium">${s.bullet}</span>`; row.addEventListener('click', () => setActive(i, true)); bulletList.appendChild(row); }); } function setIcon(icon, accent) { iconBox.className = `w-12 h-12 rounded-xl flex items-center justify-center mb-5 ${accents[accent].iconBox}`; iconBox.innerHTML = `<i data-lucide="${icon}" class="w-6 h-6"></i>`; lucide.createIcons({ attrs: { 'stroke-width': 1.5 } }); } function setBadges() { badgesLayer.innerHTML = ''; } function colorMap(name, alpha = 1) { const colors = { emerald: `rgba(16,185,129,${alpha})`, violet: `rgba(139,92,246,${alpha})`, amber: `rgba(245,158,11,${alpha})`, sky: `rgba(14,165,233,${alpha})` }; return colors[name] || `rgba(16,185,129,${alpha})`; } function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function applyHighlights(text, slideKey, badges) { const tokens = (highlightMap[slideKey] || []).slice(); let result = text; tokens.forEach((token, idx) => { const b = badges[idx]; if (!b) return; const re = new RegExp(`\\b(${escapeRegExp(token)})\\b`, 'i'); const bg = colorMap(b.color, 0.18); const border = colorMap(b.color, 0.35); result = result.replace(re, (m) => { return `<span class="rounded-md px-1.5 -mx-0.5 ring-1" style="background:${bg}; box-shadow: inset 0 0 0 1px ${border};">${m}</span>`; }); }); return result; } let index = 0; let timer; function setActive(i, manual = false) { index = i % slides.length; if (index < 0) index = slides.length - 1; const s = slides[index]; renderBullets(index); setIcon(s.icon, s.accent); highlightPill.className = `inline-flex items-center rounded-md px-2.5 py-1.5 ring-1 text-base sm:text-lg ${accents[s.accent].pill}`; highlightPill.textContent = s.pillText; highlightTail.textContent = s.tailText; bodyCopy.innerHTML = applyHighlights(s.body, s.key, s.badges); setBadges(); if (manual) { clearInterval(timer); timer = startRotation(); } } function startRotation() { return setInterval(() => setActive((index + 1) % slides.length), 4500); } renderBullets(index); setActive(0); timer = startRotation(); root.addEventListener('mouseenter', () => clearInterval(timer)); root.addEventListener('mouseleave', () => { clearInterval(timer); timer = startRotation(); }); setTimeout(() => lucide.createIcons({ attrs: { 'stroke-width': 1.5 } }), 100);
</script>
</div>