Morphiq

Components / Gravity Menu

Gravity Menu

Menu items hold stable orbits until the cursor arrives as a mass and bends their paths past it. F = G·m·r/(r² + ε²)^(3/2) — the inverse square with Plummer softening — and the ε is not a fudge — an unsoftened inverse square diverges as an item crosses the pointer, which in a discrete integrator means one frame that throws it off screen. Softening caps the force at close range, which is what N-body codes do for exactly this reason. Rest the pointer on an item and the ring holds still for it; arrow keys walk focus round the ring.

Usage

import GravityMenu from '@/components/gravity-menu'

<GravityMenu items={items} orbit={130} value={current} onSelect={setCurrent} />

Installation

npx shadcn@latest add https://morphiq.prathampatel.design/r/gravity-menu.json

Model

F = G·m·r / (r² + ε²)^(3/2)

the inverse square with Plummer softening ε · k the spring to the slot

Props

PropertyTypeDefaultDescription
itemsGravityMenuItem[][]The items, in ring order. An item without an id is known by its index.
orbitnumber130Orbital radius, px. A change is ridden out on each item's spring. Default 130.
spinnumber0.16Angular rate, radians per second. The ring holds still under a hovered, pressed or keyboard-focused item. Default 0.16.
massnumber2.6e6G·m of the pointer, px³/s². At spring · softening³ an item close to the pointer rests halfway to it. Default 2.6e6.
softeningnumber46Softening ε, px. Caps the force at close range so nothing is flung away. Default 46.
springnumber26Pull back to the orbital slot, 1/s². 0 makes it a free two-body system. Default 26.
dampingnumber7.6Damping on an item's motion about its slot, 1/s. 2 · √spring is critical. Default 7.6.
repelbooleanfalsePush instead of pull. The push lets go of the item the pointer is on, so it can still be clicked. Default false.
valuestring | number—Id of the current item, or its index if it has no id. It is marked aria-current and filled.
onSelect(id: string | number, item: GravityMenuItem, index: number) => void—Called with the item's id (or index), the item and its index when it is clicked or activated from the keyboard.