Paper Wobble
Per-pose reshoot jitter that makes any content feel hand-placed on a desk
$ pnpm dlx shadcn@latest add @remocn/paper-wobbleUsage
Wrap anything. The wrapper holds one offset for a whole stop-motion pose, then snaps to the next — the wobble of a photo that was picked up and put back down.
// src/Root.tsx
import { AbsoluteFill, Composition } from "remotion";
import { PaperWobble } from "@/components/remocn/paper-wobble";
const PaperWobbleScene = () => (
<AbsoluteFill
style={{
background: "#f1eee7",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
gap: 40,
}}
>
<PaperWobble seed="title">
<h1 style={{ fontSize: 64, color: "#26242c" }}>Shot on a desk</h1>
</PaperWobble>
<PaperWobble seed="card">
<YourCard />
</PaperWobble>
</AbsoluteFill>
);
export const RemotionRoot = () => (
<Composition
id="PaperWobble"
component={PaperWobbleScene}
durationInFrames={90}
fps={30}
width={1280}
height={720}
/>
);Give each wrapped block its own seed — two instances sharing a seed move in
lockstep, which reads as one rigid sheet rather than two objects on a desk.
Components that already carry their own jitter, like paper-sticker, do not
need this wrapper — doubling it up just doubles the shake.
The wrapper is display: inline-block and nothing else: no size, no
background, no positioning. If you pass a transform through style, it is
applied first and the jitter is appended, so your own positioning survives.
Props7
| Prop | Type | Default |
|---|---|---|
| childrenrequired | React.ReactNode— The content to wobble | |
| seed | string"wobble" Seed for the jitter — same seed, same motion | |
| amp | number1.4 Maximum offset in pixels on each axis | |
| rotAmp | number0.35 Maximum rotation in degrees | |
| step | number3 Frames per stop-motion pose — the tempo control | |
| className | string— Passed through to the wrapper div | |
| style | React.CSSProperties— Merged over the defaults; a transform here is composed before the jitter | |
- childrenrequiredReact.ReactNode
The content to wobble
- seedstring
Seed for the jitter — same seed, same motion
Default
"wobble" - ampnumber
Maximum offset in pixels on each axis
Default
1.4 - rotAmpnumber
Maximum rotation in degrees
Default
0.35 - stepnumber
Frames per stop-motion pose — the tempo control
Default
3 - classNamestring
Passed through to the wrapper div
- styleReact.CSSProperties
Merged over the defaults; a transform here is composed before the jitter