Introduction
Familiar shadcn components rebuilt for Remotion. You declare what state a component is in and when, and it renders that state as a pure function of the frame.
- At frame 0Idle
- At frame 12Hover
- At frame 30Press
- At frame 48, duration 6Loading
What makes this different from regular shadcn
In a browser, a button enters its loading state because the user clicked. In a video, it enters that state because you authored { at: 35, state: "loading" }. The component looks identical; the wiring is completely different.
This also means you get things that are impossible in a real UI: scrub backward through a form fill, play a button click at half speed, or loop a checkbox toggle indefinitely, all without any special setup.
- Not
useState - Not
onClick - Not
transition: useCurrentFrame()
Two kinds of atom
Every primitive is one of two shapes. Knowing which tells you where the frame is read and how timing reaches the component.
State atoms
Snap or smoothPure visual functions of state and theme. They never read the frame; the state comes from a prop, useCurrentState, or a transition hook like useButtonTransition.
{ at: 12, state: "hover" }Motion atoms
Loop on the frameLoop on useCurrentFrame() with no discrete states. No Date, no Math.random, no requestAnimationFrame, so they stay safe in the headless renderer.
<Caret blink={!tw.typing} />Install your first primitive
Remotion must already be set up. The shared remocn-ui core installs automatically as a registry dependency, so you only name the component you want.
$ pnpm dlx shadcn@latest add @remocn/buttoncomponents/remocn/button.tsxlib/remocn-ui/shared core
Components
The pieces a product demo is made of: a cursor that clicks, a menu that opens, a toast that lands. Each one copies into components/remocn/ with its transition hook.
- CursorAn animated cursor that follows a scripted path with click ripple and press effects
- Command MenuA keyboard-driven command palette with backdrop, typing animation, and row selection
- ToastA notification that slides in from below, holds, then auto-dismisses
- DialogA modal dialog whose opened/closed state is a pure function of the timeline
- SwitchA switch whose checked/unchecked state is a pure function of the timeline
- SliderA range slider with a draggable thumb driven by a scripted value and thumb-state timeline
- TooltipA small floating label that appears above an anchor on hover
- Typing IndicatorA motion atom that renders N bouncing dots driven directly by useCurrentFrame
Blocks
Complete, shippable scenes built from these primitives. Each block orchestrates the cursor, fields and feedback into one coherent story you can drop into a Sequence.
8- Chat Flow360 framesA messaging conversation that types outgoing messages, shows typing indicators, and pops in incoming replies with reactions
- Telegram Chat Flow360 framesTelegram-styled conversation with tailed bubbles, delivery checks, typing status, and reaction chips
- iMessage Chat Flow360 framesiMessage-styled conversation with gray incoming and blue outgoing bubbles, typing indicator, Delivered label, and tapback reactions
- Signup Flowstate-drivenA cursor-driven signup card — labeled fields fill top-to-bottom, then submit with success feedback
- Checkout Flowstate-drivenA cursor-driven checkout card with a pricing toggle, card input, terms checkbox, and payment confirmation
- Onboarding Stepper Flow175 framesA multi-step onboarding scene where a stepper advances through form panels and finishes on a success state
- AI Prompt Flow230 framesA full prompt-to-answer scene — the prompt types itself, the button runs to loading, a skeleton reveals, and the answer crossfades in
- Settings Toggle Flowstate-drivenTwo-column settings card with a blur-in entrance and a cursor-driven switch, select, slider, and save