{
    "id": "bhaskar/fan-timeline-carousel",
    "kind": "component",
    "title": "Fan Timeline Carousel",
    "summary": "Horizontal timeline where cards fan out from one point. Click a card or use the arrows to move through the milestones.",
    "author": "Admin",
    "stars": 0,
    "url": "https://ownlyplans.com/bhaskar/fan-timeline-carousel/",
    "stack": [],
    "tools": [
        "claude-code"
    ],
    "difficulty": "beginner",
    "license": "cc-by-4.0",
    "version": "1.0",
    "overview": "",
    "steps": [],
    "files": [],
    "install": "",
    "how_to_use": "Use the component code (html, css, js, or react) directly, or run the install command.",
    "component": {
        "category": "Motion and entrances",
        "html": "<div class=\"tl\"><div class=\"tr\"></div><div class=\"ctl\"><button class=\"pv\" type=\"button\">‹</button><span class=\"ct\"></span><button class=\"nx\" type=\"button\">›</button></div></div>",
        "css": ".tl{position:relative;width:100%;height:100%;min-height:380px;overflow:hidden;font-family:system-ui,-apple-system,sans-serif;color:#eee;}.tr{position:absolute;left:50%;top:0;height:340px;transition:transform .6s cubic-bezier(.3,1.1,.4,1)}.yr{position:absolute;top:70px;font:700 64px system-ui;color:#262626}.cd{position:absolute;top:150px;width:150px;height:180px;background:#1b1b1b;border:1px solid #2a2a2a;border-radius:14px;padding:12px;box-sizing:border-box;cursor:pointer;opacity:.5;transform:scale(.86);transform-origin:50% 100%;transition:transform .5s cubic-bezier(.3,1.3,.5,1),opacity .4s}.cd.on{opacity:1;transform:scale(1.08)}.cd small{display:block;font-size:10px;color:#777}.cd b{display:block;font-size:13px;margin-top:2px}.cd svg{position:absolute;left:10px;right:10px;bottom:10px;width:130px;height:80px}.fl{position:absolute;left:0;top:0;height:1px;background:rgba(150,150,170,.5);transform-origin:0 0;pointer-events:none}.ctl{position:absolute;bottom:8px;left:0;right:0;display:flex;justify-content:center;align-items:center;gap:12px;font-size:12px;color:#888}.ctl button{width:30px;height:30px;border-radius:50%;border:1px solid #2a2a2a;background:#1b1b1b;color:#eee;cursor:pointer;font-size:16px}",
        "js": "(function(){var R=document.querySelector(\".tl\"),tr=R.querySelector(\".tr\"),ct=R.querySelector(\".ct\");var D=[[\"Oct 14 ’25\",\"Offline drafts\",[3,5,4,6,5,7]],[\"Nov 20 ’25\",\"Weekly signups double\",[2,3,5,4,7,9]],[\"Jan 8 ’26\",\"Shared spaces\",[4,4,6,7,6,8]],[\"Mar 2 ’26\",\"Public API\",[1,3,4,6,8,9]]];var P=164,a=1,n=D.length,fl=[];D.forEach(function(d,i){var l=document.createElement(\"div\");l.className=\"fl\";tr.appendChild(l);fl.push(l);var c=document.createElement(\"div\");c.className=\"cd\";c.style.left=i*P+\"px\";var pts=d[2].map(function(v,k){return (k*22)+\",\"+(78-v*8)}).join(\" \");c.innerHTML=\"<small>\"+d[0]+\"</small><b>\"+d[1]+\"</b><svg viewBox=\\\"0 0 110 80\\\"><polyline points=\\\"\"+pts+\"\\\" fill=\\\"none\\\" stroke=\\\"#0a84ff\\\" stroke-width=\\\"2\\\"/></svg>\";c.onclick=function(){go(i)};tr.appendChild(c)});[[\"’25\",-10],[\"’26\",2*P+10]].forEach(function(y){var e=document.createElement(\"div\");e.className=\"yr\";e.textContent=y[0];e.style.left=y[1]+\"px\";tr.appendChild(e)});function go(i){a=Math.max(0,Math.min(n-1,i));tr.style.transform=\"translateX(\"+(-(a*P+75))+\"px)\";[].forEach.call(tr.querySelectorAll(\".cd\"),function(c,k){c.classList.toggle(\"on\",k===a)});var x1=a*P+75,y1=12,y2=150;fl.forEach(function(l,k){var x2=k*P+75,dx=x2-x1,dy=y2-y1;l.style.left=x1+\"px\";l.style.top=y1+\"px\";l.style.width=Math.sqrt(dx*dx+dy*dy)+\"px\";l.style.transform=\"rotate(\"+Math.atan2(dy,dx)+\"rad)\"});ct.textContent=(a+1)+\" / \"+n}R.querySelector(\".pv\").onclick=function(){go(a-1)};R.querySelector(\".nx\").onclick=function(){go(a+1)};go(1)})();",
        "react": "",
        "dependencies": [],
        "install": "",
        "licence_notice": ""
    }
}