モーダル
JavaScript

Spring Bounce Toast

スプリング物理で弾むように出現するトースト通知。

HTML
<button class="sbt-trigger" id="sbt-trigger">Show Toast</button>
<div class="sbt-toast" id="sbt-toast">
  <span>Action completed!</span>
</div>
CSS
.sbt-trigger {
  padding: 12px 28px;
  background: #6366f1;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}
.sbt-toast {
  position: fixed;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%) translateY(100px);
  background: #1e293b;
  color: #e2e8f0;
  padding: 14px 28px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 8px 30px rgba(0,0,0,0.3);
  z-index: 100;
}
JavaScript
const toast = document.getElementById('sbt-toast');
document.getElementById('sbt-trigger').addEventListener('click', function() {
  let y = 100, vy = -18, spring = 0.15, damping = 0.7;
  function step() {
    vy += spring * y;
    vy *= damping;
    y -= vy;
    toast.style.transform = 'translateX(-50%) translateY(' + y + 'px)';
    if (Math.abs(y) > 0.5 || Math.abs(vy) > 0.5) {
      requestAnimationFrame(step);
    } else {
      toast.style.transform = 'translateX(-50%) translateY(0)';
      setTimeout(function() {
        let closeY = 0;
        function close() {
          closeY += 5;
          toast.style.transform = 'translateX(-50%) translateY(' + closeY + 'px)';
          if (closeY < 120) requestAnimationFrame(close);
        }
        close();
      }, 2000);
    }
  }
  step();
});