Skip to content

Pendulum Menu

Menu items that hang from a rail and swing on real pendulum physics, nudging their neighbours.

Proplayfuleditorial
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.

Preview
Hover or click an item

Props

2600
1.1
No runtime dependencies
"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
  // ---------------------------------------------------------------
}
Notes

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.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

Featured
NewPro

A mega-menu that reads where the pointer is heading, so cutting the corner never steals the submenu.

menunavhover
Featured
NewPro

A banner hanging from its fixings as real Verlet cloth — previous-position integration, relaxation passes and a fixed timestep behind an accumulator.

canvasphysicssimulation
Featured

Magnetic Button

components

A button whose label leans toward the cursor with a springy pull.

buttoncursorspring