How LunaTV Implements Framer Motion Animations: A Technical Deep Dive

LunaTV leverages Framer Motion v12.18.1 to drive fluid UI animations through variant-based state machines, motion component wrappers, and AnimatePresence orchestration for mount/unmount transitions.

The MoonTechLab/LunaTV repository demonstrates production-grade React animation patterns using Framer Motion. This technical examination reveals how the codebase structures animation architecture, from dependency configuration in package.json to the sophisticated multi-level selector implementation featuring dynamic transition controls.

Framer Motion Configuration and Dependencies

According to the LunaTV source code, Framer Motion is registered as a core dependency in the project's package.json manifest. The library is pinned to version 12.18.1, ensuring consistent animation behavior across development and production environments.

Components throughout the application import animation primitives from the framer-motion package:

import { motion, AnimatePresence } from 'framer-motion'

This import pattern appears in key UI components, including the multi-level selector located at src/components/MultiLevelSelector.tsx.

Core Animation Architecture

Motion Component Wrappers

LunaTV implements animations by wrapping standard JSX elements with Framer Motion's motion factory. This transformation converts static DOM elements into animatable entities capable of responding to gesture and state changes.

In src/components/MultiLevelSelector.tsx, standard div and ul elements become motion.div and motion.ul, enabling the component to accept animation-specific props like variants, initial, and animate.

Variant-Based State Machines

The repository employs variants—declarative state objects that define visual appearances for different animation phases. Each variant specifies target CSS properties for states including initial, animate, and exit.

const listVariants = {
  hidden: { opacity: 0, y: -10 },
  visible: { 
    opacity: 1, 
    y: 0, 
    transition: { staggerChildren: 0.05 } 
  }
}

This pattern allows LunaTV to orchestrate complex, multi-element animations through single state changes, with the parent variant automatically coordinating child element transitions via staggerChildren timing.

Multi-Level Selector Implementation

Animated Dropdown Transitions

The primary demonstration of LunaTV's Framer Motion implementation appears in the multi-level selector component. This UI element handles selection changes through sliding transitions with smooth easing curves.

The component structure utilizes AnimatePresence to manage the lifecycle of dropdown lists, ensuring elements animate out gracefully before unmounting:

<AnimatePresence>
  <motion.ul
    variants={listVariants}
    initial="hidden"
    animate="visible"
    exit="hidden"
  >
    {options.map(opt => (
      <motion.li
        key={opt.value}
        whileHover={{ scale: 1.05 }}
        onClick={() => onSelect(opt.value)}
      >
        {opt.label}
      </motion.li>
    ))}
  </motion.ul>
</AnimatePresence>

Stop Motion Toggle Feature

A distinctive feature within the LunaTV selector is the "stop motion" option (Chinese: 定格动画), which provides users control over animation playback. This functionality toggles between fluid animated transitions and static state changes.

The implementation switches between variant states based on a boolean flag:

const variants = {
  moving: { 
    rotate: 360, 
    transition: { repeat: Infinity, duration: 2 } 
  },
  still: { rotate: 0 }
}

<motion.div
  animate={stop ? 'still' : 'moving'}
  variants={variants}
/>

When stop is true, the component immediately settles to the still variant, bypassing transition animations entirely.

Advanced Animation Patterns

Gesture-Based Interactions

Beyond entrance and exit animations, LunaTV incorporates interactive feedback through Framer Motion's gesture props. The whileHover and whileTap properties provide immediate visual response to user input without requiring explicit state management:

<motion.li
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
>
  Interactive Item
</motion.li>

These props accept transform values that apply temporarily during user interaction, reverting automatically when the gesture ends.

Staggered List Orchestration

For multi-element reveals, the codebase leverages staggerChildren within variant definitions. This property delays the animation start of each child element by a specified duration (0.05 seconds in the selector implementation), creating sequential rather than simultaneous entrance effects.

The parent container defines the stagger timing, while child elements reference simplified variants that inherit the delay sequence:

const containerVariants = {
  visible: {
    transition: { staggerChildren: 0.05 }
  }
}

const itemVariants = {
  hidden: { opacity: 0, y: 10 },
  visible: { opacity: 1, y: 0 }
}

Summary

  • LunaTV uses Framer Motion v12.18.1 as specified in package.json to handle all UI animations
  • The multi-level selector at src/components/MultiLevelSelector.tsx serves as the primary implementation reference
  • Variant-based state machines manage animation phases (initial, animate, exit) declaratively
  • AnimatePresence wraps components requiring mount/unmount animations to enable exit transitions
  • Gesture props (whileHover, whileTap) provide immediate interactive feedback without complex state logic
  • Staggered children timing creates sequential reveal effects for lists and multi-element components
  • The "stop motion" feature demonstrates dynamic variant switching to disable animations conditionally

Frequently Asked Questions

What version of Framer Motion does LunaTV use?

LunaTV specifies Framer Motion version 12.18.1 in its package.json dependency manifest. This version provides the variant system, AnimatePresence component, and gesture handling utilized throughout the application's animation architecture.

How does the multi-level selector handle list animations?

The selector uses motion.ul with variants defining hidden and visible states, wrapped in AnimatePresence for exit animations. It implements staggerChildren: 0.05 in the parent variant to create sequential item reveals, while individual motion.li elements use whileHover for interactive scaling effects.

What is the "stop motion" feature in LunaTV?

The "stop motion" option (定格动画) allows users to disable fluid animations, switching components to static state changes instead. Implemented in the multi-level selector, this feature conditionally selects between moving and still variants based on user preference, effectively setting animate={stop ? 'still' : 'moving'} on motion components.

Where is the main animation logic located in the repository?

The primary animation implementation resides in src/components/MultiLevelSelector.tsx, which demonstrates Framer Motion patterns including variant definitions, AnimatePresence usage, and gesture props. Additional components throughout the repository follow this pattern by importing { motion } from framer-motion and applying similar wrapper-based animation strategies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →