{
    "id": "bhaskar/animated-toast-stack",
    "kind": "component",
    "title": "Animated Toast Stack",
    "summary": "Fire title, promise, success and error toasts from six screen positions. They stack, fan out on hover, auto dismiss and clear on demand.",
    "author": "Admin",
    "stars": 0,
    "url": "https://ownlyplans.com/bhaskar/animated-toast-stack/",
    "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": "Feedback",
        "html": "<div class=\"ts\"><div class=\"ctl\"><h4>Open a real toast</h4><p>Toasts render fixed on the screen. Change position to open a toast from that edge.</p><div class=\"bs\"><button data-k=\"title\"><i class=\"ck\"></i>Title only</button><button data-k=\"promise\"><i class=\"sp\"></i>Promise</button><button data-k=\"success\"><i class=\"ck\"></i>Success</button><button data-k=\"error\"><i class=\"xx\"></i>Error</button><button class=\"clr\">Clear</button></div><div class=\"ps\"><button data-p=\"top-left\">top-left</button><button data-p=\"top-center\">top-center</button><button data-p=\"top-right\">top-right</button><button data-p=\"bottom-left\">bottom-left</button><button data-p=\"bottom-center\">bottom-center</button><button data-p=\"bottom-right\" class=\"on\">bottom-right</button></div></div><div class=\"vp\"></div></div>",
        "css": ".ts{position:relative;width:440px;height:330px;font-family:system-ui,-apple-system,sans-serif;color:#f1f1f1;overflow:hidden}.ctl{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);text-align:center;display:grid;justify-items:center;gap:12px}.ctl h4{margin:0;font-size:14px}.ctl p{margin:0;max-width:240px;font-size:11.5px;line-height:1.45;color:#8a8a8a}.bs,.ps{display:flex;flex-wrap:wrap;justify-content:center;gap:7px}.bs button{display:inline-flex;align-items:center;gap:7px;border:1px solid #2a2a2a;background:#1b1b1b;color:#f1f1f1;font:600 11.5px/1 inherit;padding:9px 13px;border-radius:999px;cursor:pointer;transition:.2s}.bs button:hover{background:#262626}.bs .clr{border-color:transparent;background:none;color:#8a8a8a}.ps button{border:0;background:#1b1b1b;color:#8a8a8a;font:500 10px/1 inherit;padding:7px 10px;border-radius:999px;cursor:pointer;transition:.25s}.ps button.on{background:#f3f3f3;color:#111}.bs i{position:relative;width:11px;height:11px;display:block}.ck::after{content:\"\";position:absolute;left:3px;top:0;width:4px;height:8px;border:solid currentColor;border-width:0 1.6px 1.6px 0;transform:rotate(45deg)}.xx::before,.xx::after{content:\"\";position:absolute;left:5px;top:-1px;width:1.6px;height:12px;background:currentColor;transform:rotate(45deg)}.xx::after{transform:rotate(-45deg)}.sp{border:1.6px solid #555;border-top-color:#fff;border-radius:50%;animation:ts-sp .8s linear infinite}@keyframes ts-sp{to{transform:rotate(360deg)}}.vp{position:absolute;inset:0;pointer-events:none}.stk{position:absolute;width:210px;height:44px;pointer-events:auto}.stk.top-left{left:10px;top:10px}.stk.top-center{left:50%;margin-left:-105px;top:10px}.stk.top-right{right:10px;top:10px}.stk.bottom-left{left:10px;bottom:10px}.stk.bottom-center{left:50%;margin-left:-105px;bottom:10px}.stk.bottom-right{right:10px;bottom:10px}.tt{position:absolute;left:0;right:0;height:44px;display:flex;align-items:center;gap:10px;padding:0 12px;border-radius:12px;background:#f3f3f3;color:#111;font:600 12px/1.2 inherit;box-shadow:0 10px 26px rgba(0,0,0,.4);transform-origin:center;transition:transform .45s cubic-bezier(.3,1.2,.4,1),opacity .3s;transform:translateY(calc(var(--d)*var(--i)*7px)) scale(calc(1 - var(--i)*.05));opacity:calc(1 - var(--i)*.22);z-index:calc(10 - var(--i))}.stk:hover .tt{transform:translateY(calc(var(--d)*var(--i)*52px));opacity:1}.tt.in{animation:tt-in .45s cubic-bezier(.3,1.3,.4,1)}@keyframes tt-in{from{opacity:0;transform:translateY(calc(var(--d)*-30px))}}.tt small{display:block;font-weight:500;color:#555;margin-top:2px}.tt .ic{flex:none;width:18px;height:18px;border-radius:50%;display:grid;place-items:center;color:#fff;background:#111;font-size:10px}.tt.success .ic{background:#16a34a}.tt.error .ic{background:#dc2626}.tt .ic.sp{background:none;border:2px solid #bbb;border-top-color:#111}",
        "js": "(function(){var vp=document.querySelector('.vp'),pos='bottom-right',stk=null,n=0;function box(){if(stk&&stk.className.indexOf(pos)>-1)return stk;vp.innerHTML='';stk=document.createElement('div');stk.className='stk '+pos;stk.style.setProperty('--d',pos.indexOf('top')===0?1:-1);vp.appendChild(stk);return stk}function lay(){var s=stk;if(!s)return;var t=[].slice.call(s.children).reverse();t.forEach(function(e,i){e.style.setProperty('--i',i)})}function add(t,k,sub){var b=box(),e=document.createElement('div');e.className='tt in '+k;e.style.setProperty('--d',pos.indexOf('top')===0?1:-1);e.innerHTML='<span class=\"ic'+(k==='promise'?' sp':'')+'\">'+(k==='success'?'\\u2713':k==='error'?'\\u2715':k==='promise'?'':'\\u2713')+'</span><div>'+t+(sub?'<small>'+sub+'</small>':'')+'</div>';b.appendChild(e);if(b.children.length>4)b.firstChild.remove();lay();setTimeout(function(){e.classList.remove('in')},500);var life=k==='promise'?5200:4200;setTimeout(function(){rm(e)},life);return e}function rm(e){if(!e.parentNode)return;e.style.opacity=0;setTimeout(function(){var p=e.parentNode;if(p){e.remove();lay()}},300)}document.querySelectorAll('.bs button[data-k]').forEach(function(b){b.onclick=function(){var k=b.dataset.k;if(k==='title')add('Event created');else if(k==='success')add('Changes saved','success','Your workspace is up to date.');else if(k==='error')add('Upload failed','error','Check your connection.');else{var e=add('Saving changes...','promise');setTimeout(function(){if(!e.parentNode)return;e.className='tt success';e.innerHTML='<span class=\"ic\">\\u2713</span><div>Saved<small>All changes synced.</small></div>'},1600)}}});document.querySelector('.clr').onclick=function(){if(stk)[].slice.call(stk.children).forEach(rm)};document.querySelectorAll('.ps button').forEach(function(b){b.onclick=function(){document.querySelectorAll('.ps button').forEach(function(x){x.classList.toggle('on',x===b)});pos=b.dataset.p;box();add('Toast from '+pos)}})})();",
        "react": "",
        "dependencies": [],
        "install": "",
        "licence_notice": ""
    }
}