<section class="demo">
<div class="demo__dock" id="dock">
<button type="button" class="demo__icon" data-tone="a">A</button>
<button type="button" class="demo__icon" data-tone="b">B</button>
<button type="button" class="demo__icon" data-tone="c">C</button>
<button type="button" class="demo__icon" data-tone="d">D</button>
<button type="button" class="demo__icon" data-tone="e">E</button>
</div>
</section>.demo {
min-height: 100dvh;
display: grid;
place-items: center;
background: #08080a;
font-family: "Helvetica Neue", system-ui, sans-serif;
}
.demo__dock {
display: flex;
align-items: flex-end;
gap: 10px;
padding: 14px 16px 12px;
border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: rgba(16, 16, 20, 0.88);
}
.demo__icon {
width: 44px;
height: 44px;
border: 0;
border-radius: 14px;
color: #f4f4f2;
font: 600 13px/1 "Helvetica Neue", system-ui, sans-serif;
cursor: pointer;
transform-origin: 50% 100%;
will-change: transform;
}
.demo__icon[data-tone="a"] { background: #2b2f4a; }
.demo__icon[data-tone="b"] { background: #23262a; }
.demo__icon[data-tone="c"] { background: #1b3350; }
.demo__icon[data-tone="d"] { background: #3a3123; }
.demo__icon[data-tone="e"] { background: #4a2422; }const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const dock = document.querySelector("#dock");
const icons = gsap.utils.toArray(".demo__icon");
const MAX = 1.85;
const RANGE = 88;
function magnify(clientX) {
icons.forEach(function (icon) {
const rect = icon.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const dist = Math.abs(clientX - cx);
const t = Math.max(0, 1 - dist / RANGE);
const scale = 1 + (MAX - 1) * t * t;
gsap.to(icon, { scale: scale, duration: reduce ? 0 : 0.28, ease: "power3.out", overwrite: "auto" });
});
}
function reset() {
gsap.to(icons, { scale: 1, duration: 0.45, ease: "power3.out" });
}
dock.addEventListener("pointermove", function (event) { magnify(event.clientX); });
dock.addEventListener("pointerleave", reset);
const mid = icons[2].getBoundingClientRect();
magnify(mid.left + mid.width / 2);