# Magnetic wrap (goodtabs UI)

A wrapper that pulls one control toward the pointer within a radius, then eases back.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/magnetic-wrap.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/magnetic-wrap`

## Usage

```tsx
import { MagneticWrap } from "@/components/ui/magnetic-wrap"

<MagneticWrap radius={120}>
  <Button>Start building</Button>
</MagneticWrap>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| radius | `number` | `120` | How far from the centre the pull reaches, in px. |
| strength | `number` | `0.5` | How much of the pointer's offset the control follows near its centre, from 0 to 1. |

## When to use

- The one primary action in a hero or a closing section
- A short row of round icon buttons on a marketing page
- Anywhere a control should feel inviting before it is pressed

## When not to use

- App chrome, forms and toolbars people use all day: a moving target is slower to hit
- Rows of links or text, where neighbours would drift apart
- More than a few on one page, because each adds a window listener

## Notes for agents

- GSAP installs from npm under GSAP's own licence. No GSAP code ships in this registry
- Wrap exactly one control. The wrapper moves an inner box, so the child's own transforms keep working
- It listens on the window so it can react outside its own box, and only on a fine pointer with motion allowed
- Keyboard focus never pulls. On touch and under reduced motion the control sits still

## The maths

- Pull is s × d × (1 - t²)², with t = d / r, so it is 0 at the centre and at the edge and crossing the radius never jumps.
- It peaks at d = r / √5, which is 63px for a 140px radius.
- The peak move is 0.286 × s × r, so strength 0.5 at 140px moves the control 20px.

Docs: https://ui.goodtabs.co/components/magnetic-wrap