Pendulum Menu
Menu items that hang from a rail and swing on real pendulum physics, nudging their neighbours.
- Category
- Animations
- Added
- 2026-09-21
- Deps
- none
- Updated
- 2026-09-21
This is a viberdy Pro component
The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.
Props
"use client";
import { useCallback, useRef } from "react";
type Item = { label: string; L: number; theta: number; omega: number };
export function PendulumMenu({
labels = ["Overview", "Projects", "Archive", "Contact"],
gravity = 2600,
damping = 1.1,
accent = "#d6ff00",
onSelect,
}: {
labels?: string[];
gravity?: number;
damping?: number;
/** Colour of the current item's label. */
accent?: string;
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}About this animation
This is a menu built on the actual pendulum equation rather than on easing curves that resemble one. The decision that carries it is keeping the sine: nearly every implementation substitutes the small-angle approximation, because it reduces the system to a simple spring and is easier to reason about — but that substitution makes every item swing at an identical rate no matter how hard it was pushed, and the amplitude-dependent period is precisely what makes a pendulum read as a physical object. A wide swing has to take visibly longer than a narrow one. Two supporting details keep it stable and legible. The integrator runs at a fixed hundred-and-twentieth-of-a-second substep behind an accumulator, because feeding a variable frame delta into it makes the simulation explode the first time a frame drops, and the incoming delta is clamped so a backgrounded tab does not return and run hundreds of steps at once. And the transform origin sits above each item rather than inside it, which is the difference between swinging on an arc and spinning in place. The stagger is not authored at all: each item hangs from a slightly longer arm, so it has a longer natural period and the row fans apart on its own.
Curator’s note
The one line that matters is Math.sin(theta). Linearise it and you get four identical springs; keep it and you get a pendulum.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Intent Safe Menu
animationsA mega-menu that reads where the pointer is heading, so cutting the corner never steals the submenu.
Verlet Cloth Banner
animationsA banner hanging from its fixings as real Verlet cloth — previous-position integration, relaxation passes and a fixed timestep behind an accumulator.
Magnetic Button
componentsA button whose label leans toward the cursor with a springy pull.