remocn logoremocn

Tool Menu Slide In

A horizontal pill of tool icons whips up from below the canvas, then each icon pops in with a staggered spring.

A snappy editor-style toolbar reveal. The frosted-glass panel slides up from translateY(120%) to 0% via a stiff, low-mass spring — no overshoot, no slow ramp — and as soon as it locks in place each icon pops from scale: 0 to 1 with a small caskaded delay. Every icon is wrapped in its own <Sequence> so its internal useCurrentFrame resets cleanly to zero, which keeps the spring math local and predictable.

Installation

$ pnpm dlx shadcn@latest add @remocn/tool-menu-slide-in

Usage

// src/Root.tsx
import { Composition } from "remotion";
import { ToolMenuSlideIn } from "@/components/remocn/tool-menu-slide-in";

const ToolMenuScene = () => (
  <ToolMenuSlideIn
    panelStartFrame={18}
    iconStagger={4}
    iconCount={5}
    accent="#a78bfa"
  />
);

export const RemotionRoot = () => (
  <Composition
    id="ToolMenuSlideIn"
    component={ToolMenuScene}
    durationInFrames={180}
    fps={30}
    width={1280}
    height={720}
  />
);

Props

PropTypeDefaultDescription
panelStartFrame
number18Frame at which the panel begins sliding up.
iconStagger
number4Frames of delay between each icon's pop-in spring.
iconCount
number5Number of fake tool icons to render (clamped 1–8).
accent
string"#a78bfa"Accent color used for the active icon glow and border.
panelColor
string"rgba(18, 18, 22, 0.72)"Frosted-glass fill of the menu pill.
background
string"#070708"Background color of the editor canvas.
iconBg
string"rgba(255,255,255,0.06)"Background of inactive tool icons.
speed
number1Playback speed multiplier.
className
stringOptional className passed to the root container.

Notes

Snappy, not bouncy

The slide-in spring uses stiffness: 320, damping: 20, mass: 0.6 — high stiffness with enough damping to land hard without overshoot. Tool menus that bounce read as toy-like; this one feels like macOS.

Sequence resets the icon clock

Each icon is rendered inside its own <Sequence from={...}> so that the spring inside <ToolIcon> always sees frame: 0 at the moment it should start. Don't try to compute the offset manually — let <Sequence> reset the clock for you.