Components / Motion / Magnet
Magnet beta
A button with gravity: it leans toward the cursor, then springs home when the cursor leaves.
Bring the cursor near — not even onto — the button.
Uses: Button — include its CSS alongside this one.
<div style="background:var(--k-zinc-950);border-radius:14px;display:flex;align-items:center;justify-content:center;min-height:190px"> <span class="k-mag" data-magnet><span class="k-mag-in"><button class="btn btn-lg" type="button" style="background:var(--k-on-color);color:var(--k-zinc-950);border-radius:99px;padding:0 26px">Get the parts</button></span></span> </div> <p style="font-size:12.5px;color:var(--k-ink-3);margin-top:9px">Bring the cursor near — not even onto — the button.</p>
/* KATA Magnet — a control with gravity. */
.k-mag{display:inline-block;padding:26px}
.k-mag-in{display:inline-block;transition:transform .35s cubic-bezier(.2,.8,.25,1.2);will-change:transform}
.k-mag.live .k-mag-in{transition:transform .12s ease-out}
// KATA Magnet — leans toward the cursor at a third of the distance.
document.querySelectorAll('[data-magnet]').forEach(function (zone) {
var inner = zone.querySelector('.k-mag-in');
if (!inner || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
zone.addEventListener('pointermove', function (e) {
var r = zone.getBoundingClientRect();
var dx = e.clientX - (r.left + r.width / 2);
var dy = e.clientY - (r.top + r.height / 2);
zone.classList.add('live');
inner.style.transform = 'translate(' + (dx * .32).toFixed(1) + 'px,' + (dy * .32).toFixed(1) + 'px)';
});
zone.addEventListener('pointerleave', function () {
zone.classList.remove('live');
inner.style.transform = '';
});
});
Installation
CLI
node kata-ui.mjs add magnet
Writes the part’s CSS and JS into your project. Dependencies are resolved and written with it. New to the CLI? See the CLI doc.
Manual
- Load
tokens.cssonce, before any part. - Copy the CSS tab into your stylesheet.
- Copy the HTML where it belongs. The part has a script — include it after the markup; it initializes itself.
Usage
Wrap the one control a hero lives or dies by — the call to action, the play button. The pull is a fraction of the distance (about a third), the return is a spring, and touch devices simply never feel it, which is correct: there is no cursor to lean toward.
Accessibility
Motion only: the control’s position in the layout, its focus order and its name never change, and keyboard focus does not trigger the pull. Under prefers-reduced-motion the magnet is switched off and the button sits still like its ancestors.
Anatomy
The public surface of this part, read from its own source. Class names are the API — the CSS tab above is the full contract.
.k-mag | class |
.k-mag-in | class |
.live | class |
data-magnet | data hook |
Related parts
Accordion Gallery beta
Five scenes in a row; the one you touch opens up and tells its caption.
Aurora beta
A slow wash of color behind a hero — the accent and the core, drifting under glass.
Beam border beta
A single point of light travels the edge of a card. The beam is the core color — the one accent, in motion.
Blur In beta
Words arrive out of focus and sharpen one after another, like eyes adjusting.