Click any chip. The panel springs open from it — expanding out of the chip's rect and settling with a soft Apple-style overshoot.
// Apple-style spring easing — analytic underdamped step response const spring = (z, w) => { const wd = w * Math.sqrt(1 - z*z); return p => p >= 1 ? 1 : 1 - Math.exp(-z*w*p) * (Math.cos(wd*p) + (z*w/wd)*Math.sin(wd*p)); }; const ease = spring(0.72, 9); // ~4% overshoot, then settle function openFrom(chip) { const f = chip.getBoundingClientRect(); // FIRST: the chip const t = targetRect(chip); // LAST: top aligned to chip, centred gsap.set(modal, { visibility:'visible', left:f.left, top:f.top, width:f.width, height:f.height, borderRadius:999 }); gsap.timeline() .to(modal, { left:t.left, top:t.top, width:t.width, height:t.height, borderRadius:22, duration:0.52, ease }, 0) // shell springs .to(backdrop,{ opacity:1, duration:0.34 }, 0) .to(content, { opacity:1, y:0, duration:0.28 }, 0.16); // content lands after } // Close reverses on power3.inOut (no spring), ~35% faster.