Agent skill

Motion UI

by templetongroup in templetongroup/radiant

Production-ready UI motion system for React/Next.js. An agent skill from templetongroup/radiant.

MITAuto-check passedFrontend & Design

Install Motion UI

skills CLI
$ npx skills add templetongroup/radiant --skill motion-ui -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install templetongroup/radiant motion-ui --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/templetongroup/radiant.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/motion-ui .claude/skills/motion-ui && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
motion-ui
GitHub stars
113
Token cost
~3.5k tokens
SKILL.md length
684 words
Files
1
Skills in repo
9
Repo updated
First seen
Licence
MIT

At a glance

Production-ready UI motion system for React/Next.js. An agent skill from templetongroup/radiant.

  • Implementing animations
  • SKILL.md covers When to Use, How It Works and Examples
  • Calls npm
  • Motion patterns

What it does

Motion UI is an agent skill from templetongroup/radiant. Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Frontend & Design. It works with React, Next.js and Motion. The repository describes itself as: A local coding harness for Mac. Chat with coding agents across cloud and local models, watch every tool call in a live activity feed, and drive a real terminal — in one window… The licence is MIT.

When your agent uses it

  • Implementing animations
  • Motion patterns

Example prompts

  • “/motion-ui”

Requirements

  • Node.js

What it can do on your machine

Read from SKILL.md and the folder at commit 94838ca. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Motion UI loads about 3.5k tokens when it runs. Until then it costs about 32 tokens; SKILL.md has 684 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~32
When it runs · the whole SKILL.md, loaded when a task matches
~3.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from templetongroup/radiant at commit 94838ca, republished under its MIT licence (© templetongroup). 684 words, ~3,460 tokens.

Download SKILL.mdSave it as .claude/skills/motion-ui/SKILL.md (or your agent's skills folder).
name
motion-ui
description
Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.
metadata.origin
ECC

Motion System v4.2

Production-ready UI motion system for React / Next.js.

Focused on performance, accessibility, and usability — not decoration.

When to Use

Use this motion system when motion:

  • Guides attention (e.g., onboarding, key actions)
  • Communicates state (loading, success, error, transitions)
  • Preserves spatial continuity (layout changes, navigation)
Appropriate Scenarios
  • Interactive components (buttons, modals, menus)
  • State transitions (loading → loaded, open → closed)
  • Navigation and layout continuity (shared elements, crossfade)
Considerations
  • Accessibility: Always support reduced motion
  • Device adaptation: Adjust for low-end devices
  • Performance trade-offs: Prefer responsiveness over visual smoothness
Avoid Using Motion When
  • It is purely decorative
  • It reduces usability or clarity
  • It impacts performance negatively

How It Works

Core Principle

Motion must:

  • Guide attention
  • Communicate state
  • Preserve spatial continuity

If it does none → remove it.


Installation
bash
npm install motion

Version
  • motion/react - default for current Motion for React projects (package: motion)
  • framer-motion - legacy import path for projects that still depend on Framer Motion

Do not mix. Mixing causes conflicting internal schedulers and broken AnimatePresence contexts — components from one package will not coordinate exit animations with components from the other.

To check which version your project uses:

bash
cat package.json | grep -E '"motion"|"framer-motion"'

Always import from one source consistently:

ts
// Correct (modern)
import { motion, AnimatePresence } from "motion/react"

// Correct (legacy)
import { motion, AnimatePresence } from "framer-motion"

// Never mix both in the same project

Motion Tokens
ts
// motionTokens.ts
export const motionTokens = {
  duration: {
    fast: 0.18,
    normal: 0.35,
    slow: 0.6
  },
  // Use these as the `ease` value inside a `transition` object:
  // transition={{ duration: motionTokens.duration.normal, ease: motionTokens.easing.smooth }}
  easing: {
    smooth: [0.22, 1, 0.36, 1] as [number, number, number, number],
    sharp:  [0.4,  0, 0.2, 1] as [number, number, number, number]
  },
  distance: {
    sm: 8,
    md: 16,
    lg: 24
  }
}

Usage example:

tsx
import { motionTokens } from "@/lib/motionTokens"

<motion.div
  initial={{ opacity: 0, y: motionTokens.distance.md }}
  animate={{ opacity: 1, y: 0 }}
  transition={{
    duration: motionTokens.duration.normal,
    ease: motionTokens.easing.smooth
  }}
/>

Performance Rules

Safe

  • transform
  • opacity

Avoid

  • width / height
  • top / left

Rule: responsiveness > smoothness


Device Adaptation

The heuristic combines CPU core count and available memory for a more reliable signal. deviceMemory is available on Chrome/Android; the fallback covers Safari and Firefox.

ts
const isLowEnd =
  typeof navigator !== "undefined" && (
    // Low memory (Chrome/Android only; undefined elsewhere → treat as capable)
    (navigator.deviceMemory !== undefined && navigator.deviceMemory <= 2) ||
    // Few cores AND no memory API (covers Safari/Firefox on weak hardware)
    (navigator.deviceMemory === undefined && navigator.hardwareConcurrency <= 4)
  )

const duration = isLowEnd ? 0.2 : 0.4

Accessibility
JS (useReducedMotion)
tsx
import { motion, useReducedMotion } from "motion/react"

export function FadeIn() {
  const reduce = useReducedMotion()

  return (
    <motion.div
      initial={{ opacity: 0, y: reduce ? 0 : 24 }}
      animate={{ opacity: 1, y: 0 }}
    />
  )
}
CSS
css
@media (prefers-reduced-motion: reduce) {
  .motion-safe-transition {
    transition: opacity 0.2s;
  }

  .motion-reduce-transform {
    transform: none !important;
  }
}
Tailwind
html
<div class="motion-safe:animate-fade motion-reduce:opacity-100"></div>

Architecture & Patterns
Core Patterns
ScenarioPattern
Hover feedbackwhileHover
Tap / press feedbackwhileTap
Reveal on scrollwhileInView
Scroll-linked valueuseScroll + useTransform
Conditional mount/unmountAnimatePresence
Small layout shifts (single element, < ~300px change)layout prop
Large layout shifts or full-page reflowsAvoid layout; use CSS transitions or page-level routing instead
Complex, imperative sequencesuseAnimate

Why avoid layout on large containers? Framer's layout animation uses transform to reconcile positions, but on elements that span the full viewport or trigger deep reflow, the measurement cost causes visible jank and CLS. Prefer CSS Grid/Flexbox transitions or coordinate with layoutId on specific child elements only.

Layout & Transitions
  • Shared element transitions → layoutId (must be unique per mounted instance)
  • Enter / exit transitions → AnimatePresence (see mode guidance below)
AnimatePresence mode

Always specify mode explicitly — the default ("sync") runs enter and exit simultaneously, which causes visual overlap in most UI patterns.

modeWhen to use
"wait"Exit completes before enter starts. Use for modals, toasts, page transitions.
"sync" (default)Enter and exit overlap. Use only when overlap is intentional (e.g., crossfade carousels).
"popLayout"Exiting element is popped out of flow immediately; remaining items animate to fill. Use for lists, tabs, dismissible cards.
tsx
// Modal — always use "wait"
<AnimatePresence mode="wait">
  {open && <Modal key="modal" />}
</AnimatePresence>

// Dismissible list item — use "popLayout"
<AnimatePresence mode="popLayout">
  {items.map(item => <Card key={item.id} />)}
</AnimatePresence>

Show full SKILL.md (259 more words)Show less
Advanced Patterns (Concepts)
  • Parallax (scroll-linked transforms)
  • Scroll storytelling (sticky sections)
  • 3D tilt (pointer-based transforms)
  • Crossfade (shared layoutId)
  • Progressive reveal (clip-path)
  • Skeleton loading (looped opacity)
  • Micro-interactions (hover/tap feedback)
  • Spring system (physics-based motion)

Modal Essentials
  • Focus trap
  • Escape close
  • Scroll lock
  • ARIA roles
  • Use AnimatePresence mode="wait" so exit animation completes before the next modal enters
Full Example
tsx
import React, { useEffect, useRef, useState } from "react"
import { motion, AnimatePresence } from "motion/react"

function useFocusTrap(ref: React.RefObject<HTMLDivElement | null>, active: boolean) {
  useEffect(() => {
    if (!active || !ref.current) return
    const el = ref.current
    const focusable = el.querySelectorAll<HTMLElement>(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    )
    const first = focusable[0]
    const last  = focusable[focusable.length - 1]

    function handleKey(e: KeyboardEvent) {
      if (e.key !== "Tab") return
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault()
        last?.focus()
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault()
        first?.focus()
      }
    }

    el.addEventListener("keydown", handleKey)
    first?.focus()
    return () => el.removeEventListener("keydown", handleKey)
  }, [active, ref])
}

function useScrollLock(active: boolean) {
  useEffect(() => {
    if (!active) return
    const prev = document.body.style.overflow
    document.body.style.overflow = "hidden"
    return () => { document.body.style.overflow = prev }
  }, [active])
}

function Modal({ open, closeModal }: { open: boolean; closeModal: () => void }) {
  const ref = useRef<HTMLDivElement>(null)

  useFocusTrap(ref, open)
  useScrollLock(open)

  useEffect(() => {
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") closeModal()
    }
    if (open) window.addEventListener("keydown", onKey)
    return () => window.removeEventListener("keydown", onKey)
  }, [open, closeModal])

  return (
    // mode="wait" ensures exit animation finishes before any new modal enters
    <AnimatePresence mode="wait">
      {open && (
        <motion.div
          role="dialog"
          aria-modal="true"
          aria-labelledby="modal-title"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.2 }}
          className="fixed inset-0 flex items-center justify-center bg-black/40"
        >
          <motion.div
            ref={ref}
            initial={{ scale: 0.95, opacity: 0 }}
            animate={{ scale: 1,    opacity: 1 }}
            exit={{    scale: 0.95, opacity: 0 }}
            transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }}
            className="bg-white p-6 rounded"
          >
            <h2 id="modal-title">Dialog Title</h2>
            <button onClick={closeModal}>Close</button>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  )
}

export function Example() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button onClick={() => setOpen(true)}>Open</button>
      <Modal open={open} closeModal={() => setOpen(false)} />
    </>
  )
}

SSR Safety
  • Match initial states between server and client renders
  • Avoid implicit animation origins (always set initial explicitly)
  • Wrap motion components in "use client" in Next.js App Router

Debugging

Check:

  • Wrong import (mixing motion/react and framer-motion)
  • Missing "use client" directive in Next.js App Router
  • Missing key prop on AnimatePresence children
  • Hydration mismatch (initial state differs between SSR and client)
  • layout prop misuse on large containers causing reflow jank
  • State-driven animation not triggering (check dependency arrays)

QA
  • No CLS
  • Keyboard works
  • Focus trapped in modals
  • ARIA roles correct (role="dialog", aria-modal="true")
  • Reduced motion respected (useReducedMotion + CSS media query)
  • No hydration warnings in Next.js
  • Animations stop cleanly on unmount (no memory leaks)
  • AnimatePresence mode set explicitly on all usage sites

Anti-Patterns
  • Animating layout properties (width, height, top, left)
  • Infinite animations without purpose (always ask: what state does this communicate?)
  • Over-staggering lists (keep staggerChildren ≤ 0.1s; beyond that it feels slow)
  • Ignoring reduced motion preferences
  • Using layout on large or full-viewport containers
  • Omitting mode on AnimatePresence (default "sync" causes visual overlap)
  • Using motion purely for decoration

Philosophy

Motion is interaction design.


Final Rule

If motion does not improve UX → remove it.


Examples

Button Interaction
tsx
import { motion } from "motion/react"

export function Button() {
  return (
    <motion.button
      whileHover={{ scale: 1.02 }}
      whileTap={{ scale: 0.97 }}
      transition={{ duration: 0.15, ease: [0.4, 0, 0.2, 1] }}
    >
      Click me
    </motion.button>
  )
}

Reduced Motion Example
tsx
import { motion, useReducedMotion } from "motion/react"

export function FadeIn() {
  const reduce = useReducedMotion()

  return (
    <motion.div
      initial={{ opacity: 0, y: reduce ? 0 : 24 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: reduce ? 0.1 : 0.35, ease: [0.22, 1, 0.36, 1] }}
    />
  )
}

Stagger List
tsx
import { motion } from "motion/react"

const container = {
  hidden: {},
  visible: {
    transition: { staggerChildren: 0.08 } // keep ≤ 0.1s to avoid sluggishness
  }
}

const item = {
  hidden:  { opacity: 0, y: 10 },
  visible: { opacity: 1, y: 0,  transition: { duration: 0.3, ease: [0.22, 1, 0.36, 1] } }
}

export function List() {
  return (
    <motion.ul variants={container} initial="hidden" animate="visible">
      {[1, 2, 3].map(i => (
        <motion.li key={i} variants={item}>Item {i}</motion.li>
      ))}
    </motion.ul>
  )
}

Modal with AnimatePresence
tsx
import { motion, AnimatePresence } from "motion/react"

export function Modal({ open }: { open: boolean }) {
  return (
    <AnimatePresence mode="wait">
      {open && (
        <motion.div
          initial={{ opacity: 0, scale: 0.95 }}
          animate={{ opacity: 1, scale: 1    }}
          exit={{    opacity: 0, scale: 0.95 }}
          transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }}
        />
      )}
    </AnimatePresence>
  )
}

Scroll Parallax
tsx
import { useScroll, useTransform, motion } from "motion/react"

export function Parallax() {
  const { scrollYProgress } = useScroll()
  const y = useTransform(scrollYProgress, [0, 1], [0, -80])

  return <motion.div style={{ y }} />
}

Skeleton Loading
tsx
import { motion } from "motion/react"

export function Skeleton() {
  return (
    <motion.div
      className="bg-gray-200 h-6 w-full rounded"
      animate={{ opacity: [0.5, 1, 0.5] }}
      transition={{
        duration: 1.5,       // comfortable pulse — was missing, caused fast flash
        repeat: Infinity,
        ease: "easeInOut"
      }}
    />
  )
}

Shared Layout (Crossfade)
tsx
import { motion } from "motion/react"

// layoutId must be unique per mounted instance.
// If multiple instances can exist simultaneously, append a unique id:
// layoutId={`shared-${item.id}`}
export function Shared() {
  return <motion.div layoutId="shared" />
}

© templetongroup, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/motion-ui of templetongroup/radiant.

Open the folder on GitHubat commit 94838ca

Compare with similar skills

Motion UI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Motion UI compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Motion UI this skilltempletongroup/radiant113—~3.5kAutomated safety check: PassMIT
Chakra UI v2 to v3 Migrationchakra-ui/chakra-ui41k—~3.4kAutomated safety check: PassMIT
Motion Dev Animations199-biotechnologies/motion-dev-animations-skill1331 repos~2.8kAutomated safety check: NotesMIT
Goey Toastanl331/goey-toast1.3k—~1.3kAutomated safety check: WarnMIT
Animatedelphi-ai/animate-skill113—~1.3kAutomated safety check: PassNone
Awwwards-Level React AnimationsHainrixz/editor-pro-max264—~4.4kAutomated safety check: PassCustom licence

Similar skills

  • Chakra UI v2 to v3 Migration

    chakra-ui/chakra-ui

    Guides an upgrade from Chakra UI v2 to v3: inspect the project, swap packages, run the official codemod, then fix provider, color mode, props, theming and Next.js code.

    41k GitHub stars~3.4k tokensUpdated 4 days ago
    Frontend & DesignAuto-check passed
  • Motion Dev Animations

    199-biotechnologies/motion-dev-animations-skill

    Creates 120fps GPU-accelerated animations with Motion.dev (Framer Motion successor) for React, Next.js, Svelte, and Astro projects.

    133 GitHub starsUsed in 1 repo~2.8k tokens
    Frontend & DesignAuto-check: notes
  • Goey Toast

    anl331/goey-toast

    Install and use goey-toast — a gooey, morphing React toast component built on Sonner with Framer Motion.

    1.3k GitHub stars~1.3k tokensUpdated 1 mo ago
    Frontend & DesignAuto-check: warnings
  • Animate

    delphi-ai/animate-skill

    Animation patterns and best practices for Next.js/React applications.

    113 GitHub stars~1.3k tokensUpdated 8 mo ago
    Frontend & DesignAuto-check passed
  • Awwwards-Level React Animations

    Hainrixz/editor-pro-max

    Guides React animation work with GSAP, Motion, Anime.js and Lenis for scroll effects, page transitions, text effects and generative visuals, with a library decision table.

    264 GitHub stars~4.4k tokensUpdated 6 mo ago
    Frontend & DesignAuto-check passed
  • Motion

    softmaple/softmaple

    Animation skill for Motion (prev Framer Motion) and CSS animation.

    161 GitHub stars~1.1k tokensUpdated 2 days ago
    Frontend & DesignAuto-check passed

More from templetongroup/radiant

All 9 skills in this repo
  • Design System

    templetongroup/radiant

    A skill your agent uses to generate or audit design systems, check visual consistency, and review PRs that touch styling.

    113 GitHub stars~775 tokensUpdated 4 days ago
    Auto-check passed
  • Master Design

    templetongroup/radiant

    Design, redesign, build, audit, polish, and production-verify exceptional interfaces across web, mobile, and native apps.

    113 GitHub stars~2.9k tokensUpdated 4 days ago
    Auto-check passed
  • Tinystruct Patterns

    templetongroup/radiant

    Expert guidance for developing with the tinystruct Java framework.

    113 GitHub stars~3k tokensUpdated 4 days ago
    Auto-check passed
  • Agent Payment X402

    templetongroup/radiant

    Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets.

    113 GitHub stars~2.7k tokensUpdated 4 days ago
    Auto-check passed
  • Plan Orchestrate

    templetongroup/radiant

    Read a plan document, decompose it into steps, design a per-step agent chain from the ECC catalogue, and emit ready-to-paste /orchestrate custom prompts.

    113 GitHub stars~4.5k tokensUpdated 4 days ago
    Auto-check passed
  • Star System

    templetongroup/radiant

    Ask the user to rate the code/output just produced on a 1-5 star scale, then ask rating-appropriate follow-up questions, log the rating, and iterate until the work reaches 4+ stars.

    113 GitHub stars~2.2k tokensUpdated 4 days ago
    Auto-check passed

Questions about Motion UI

What does Motion UI do?

Production-ready UI motion system for React/Next.js. An agent skill from templetongroup/radiant. Motion UI is an agent skill from templetongroup/radiant.js.

When should I use Motion UI?

Motion UI fits situations like: implementing animations; motion patterns.

How do I install Motion UI in Claude Code?

Run `npx skills add templetongroup/radiant --skill motion-ui -a claude-code`. Or copy the skill folder (skills/motion-ui in templetongroup/radiant) into .claude/skills/motion-ui in your project. Claude Code loads it when a task matches its description.

How do I install Motion UI in Codex?

Run `npx skills add templetongroup/radiant --skill motion-ui -a codex`. Or copy the skill folder (skills/motion-ui in templetongroup/radiant) into .agents/skills/motion-ui in your project. Codex loads it when a task matches its description.

Can I use Motion UI in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add templetongroup/radiant --skill motion-ui -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/motion-ui, .gemini/skills/motion-ui, .github/skills/motion-ui and .opencode/skills/motion-ui in your project.

What does Motion UI need to run?

Going by SKILL.md and its folder, Motion UI needs the command-line tools its instructions call (npm). Our summary lists: Node.js.

Does Motion UI access the network?

SKILL.md contains no URLs. Its commands use npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Motion UI safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Motion UI use?

Motion UI is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Motion UI use?

About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Motion UI?

Skills that share tags, products or a category with Motion UI: Chakra UI v2 to v3 Migration (chakra-ui/chakra-ui, 41k stars), Motion Dev Animations (199-biotechnologies/motion-dev-animations-skill, 133 stars), Goey Toast (anl331/goey-toast, 1.3k stars) and Animate (delphi-ai/animate-skill, 113 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Motion UI?

templetongroup (a GitHub user) maintains it in templetongroup/radiant, which has 113 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on October 6, 2026.

Source: templetongroup/radiant on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.