Claude Code dan Framer Motion: panduan praktis Motion for React
Gunakan Claude Code dengan Framer Motion/Motion for React: prompt, contoh TSX, pitfall, aksesibilitas, dan verifikasi.
Banyak developer masih mencari dengan nama Framer Motion, tetapi dokumentasi resmi terbaru menyebut library ini sebagai Motion for React. Untuk kode baru, install motion dan import API React dari motion/react. Jika aplikasi lama sudah konsisten memakai framer-motion, jangan mencampur kedua gaya import tanpa keputusan tim. Untuk implementasi baru, jadikan dokumentasi resmi Motion for React sebagai acuan.
Claude Code bisa mempercepat pekerjaan animasi, tetapi tidak otomatis memahami konteks produk. Prompt seperti “buat lebih smooth” sering menghasilkan gerakan terlalu ramai, melewatkan Reduced Motion, atau membuat exit animation gagal karena parent component unmount terlalu cepat. Masa mencoba pola ini di dashboard internal: versi pertama tampak bagus saat demo, tetapi card bergerak terlalu jauh, notification hilang tanpa exit, dan header berbasis scroll terasa berat di laptop sederhana.
Artikel ini memperlakukan Claude Code sebagai kolaborator yang perlu batas jelas. Kita tentukan intent, scope, aksesibilitas, dan cara verifikasi sebelum meminta perubahan kode. Contoh TSX di bawah bisa ditempel ke proyek React setelah npm install motion. Untuk Next.js atau Astro, simpan bagian ini sebagai client component.
Mulai dari batas desain
Animasi bukan dekorasi. Animasi harus menjelaskan perubahan state. Sebelum memberi tugas ke Claude Code, tulis batasnya.
| Keputusan | Yang diberikan ke Claude Code | Yang direview |
|---|---|---|
| Tujuan | State change mana yang perlu dibantu | Animasi membantu pemahaman |
| Scope | File yang boleh dan tidak boleh disentuh | Tidak ada refactor yang tidak terkait |
| API | motion/react dan Reduced Motion | Import dan behavior sesuai docs |
| Verifikasi | Manual test, keyboard, device lambat | Test mengikuti alur nyata user |
Alurnya bisa dibuat sederhana:
Intent dan batasan
-> prompt Claude Code
-> implementasi Motion for React
-> verifikasi manual dan aksesibilitas
-> prompt lanjutan yang spesifik
Prompt pertama yang praktis:
Tambahkan animasi Motion for React ke React component yang sudah ada.
Syarat:
- Import API Motion baru dari `motion/react`
- Jangan ubah data fetching, form submit, atau routing
- Dukung Reduced Motion
- Prioritaskan opacity dan transform
- Hindari layout shift
- Sertakan checklist manual test setelah perubahan
Detail import penting karena banyak contoh lama masih memakai framer-motion. Jika standar repo tidak ditulis, Claude Code mudah mengambil pola yang tidak konsisten.
Use case 1: daftar card yang masuk natural
Dashboard, daftar artikel, dan feature card cocok memakai stagger yang tenang. Tujuannya bukan membuat setiap card terlihat spektakuler, tetapi memberi urutan baca. Dalam pengujian Masa, stagger 0,06 sampai 0,09 detik terasa pas untuk enam card; lebih lama dari itu membuat UI terasa menunggu.
import { motion, useReducedMotion } from "motion/react";
type Feature = {
id: string;
title: string;
body: string;
metric: string;
};
const demoFeatures: Feature[] = [
{
id: "review",
title: "Antrian review",
body: "Perubahan dari Claude Code yang perlu dicek manusia.",
metric: "8 item",
},
{
id: "motion",
title: "Perbaikan motion",
body: "Transisi pendek menjelaskan perubahan tanpa memperlambat kerja.",
metric: "14%",
},
{
id: "a11y",
title: "Reduced Motion",
body: "Gerakan besar berubah menjadi fade yang lebih tenang.",
metric: "Siap",
},
];
export function AnimatedFeatureCards({
items = demoFeatures,
}: {
items?: Feature[];
}) {
const shouldReduceMotion = useReducedMotion();
const container = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: shouldReduceMotion ? 0 : 0.08,
},
},
};
const card = {
hidden: {
opacity: 0,
y: shouldReduceMotion ? 0 : 16,
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.32,
ease: "easeOut",
},
},
};
return (
<motion.section
aria-label="Feature cards"
variants={container}
initial="hidden"
animate="visible"
style={{
display: "grid",
gap: 16,
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
}}
>
{items.map((item) => (
<motion.article
key={item.id}
variants={card}
whileHover={shouldReduceMotion ? undefined : { y: -4 }}
style={{
border: "1px solid #d9e2ec",
borderRadius: 12,
padding: 20,
background: "#ffffff",
boxShadow: "0 8px 24px rgba(15, 23, 42, 0.08)",
}}
>
<p style={{ margin: 0, color: "#2563eb", fontWeight: 700 }}>
{item.metric}
</p>
<h3 style={{ margin: "8px 0", fontSize: 18 }}>{item.title}</h3>
<p style={{ margin: 0, lineHeight: 1.7, color: "#475569" }}>
{item.body}
</p>
</motion.article>
))}
</motion.section>
);
}
Review tiga hal: key stabil, gerakan memakai transform, dan Reduced Motion menghilangkan perpindahan besar. Prompt lanjutan yang baik: “Pertahankan stagger, tetapi daftar harus tetap langsung bisa digunakan saat ada 12 card.”
Use case 2: notification dengan exit animation
AnimatePresence membuat element tetap bisa dianimasikan ketika keluar dari React tree. Dokumentasi AnimatePresence menekankan bahwa direct children membutuhkan key stabil. Kesalahan umum adalah membuat seluruh container notification conditional, sehingga parent hilang sebelum child menjalankan exit.
import { useState } from "react";
import { AnimatePresence, motion } from "motion/react";
type Toast = {
id: number;
message: string;
};
let nextToastId = 1;
export function AnimatedNotifications() {
const [toasts, setToasts] = useState<Toast[]>([
{ id: 0, message: "Berhasil disimpan" },
]);
function addToast() {
const id = nextToastId++;
setToasts((current) => [
...current,
{ id, message: `Background job ${id} selesai` },
]);
}
function dismissToast(id: number) {
setToasts((current) => current.filter((toast) => toast.id !== id));
}
return (
<div>
<button type="button" onClick={addToast}>
Tambah notification
</button>
<div
aria-live="polite"
style={{
position: "fixed",
right: 24,
top: 24,
display: "grid",
gap: 12,
width: "min(360px, calc(100vw - 48px))",
}}
>
<AnimatePresence initial={false} mode="popLayout">
{toasts.map((toast) => (
<motion.div
layout
key={toast.id}
initial={{ opacity: 0, x: 40, scale: 0.96 }}
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 40, scale: 0.96 }}
transition={{ duration: 0.2, ease: "easeOut" }}
style={{
borderRadius: 10,
border: "1px solid #cbd5e1",
background: "#ffffff",
padding: 16,
boxShadow: "0 12px 30px rgba(15, 23, 42, 0.16)",
}}
>
<p style={{ margin: "0 0 12px", color: "#0f172a" }}>
{toast.message}
</p>
<button type="button" onClick={() => dismissToast(toast.id)}>
Tutup
</button>
</motion.div>
))}
</AnimatePresence>
</div>
</div>
);
}
Minta Claude Code memeriksa apakah container tetap mounted saat tidak ada notification, tombol bisa dipakai dengan keyboard, dan aria-live tidak terlalu ramai. Notification muncul berulang selama sesi kerja, jadi perilaku yang tenang lebih penting daripada efek visual.
Use case 3: progress baca dengan scroll
Dokumentasi panjang, onboarding, dan landing page sering butuh orientasi. useScroll memberi progress halaman atau element sebagai MotionValue. Dengan useSpring, progress bar terasa lebih stabil. Jangan ubah semua section menjadi parallax; saat Reduced Motion aktif, hilangkan perpindahan besar.
import { useRef } from "react";
import {
motion,
useReducedMotion,
useScroll,
useSpring,
useTransform,
} from "motion/react";
const sections = [
{
title: "Kunci requirement",
body: "Sebelum Claude Code mengedit, tulis tujuan, target file, dan batasan.",
},
{
title: "Gerakkan sedikit",
body: "Mulai dari opacity dan transform agar motion membantu pemahaman.",
},
{
title: "Verifikasi alur nyata",
body: "Cek device lambat, keyboard, dan Reduced Motion sebelum publish.",
},
];
export function ScrollReadingProgress() {
const articleRef = useRef<HTMLElement | null>(null);
const shouldReduceMotion = useReducedMotion();
const { scrollYProgress } = useScroll({
target: articleRef,
offset: ["start start", "end end"],
});
const scaleX = useSpring(scrollYProgress, {
stiffness: 120,
damping: 28,
mass: 0.2,
});
const y = useTransform(scrollYProgress, [0, 1], [0, -48]);
return (
<article ref={articleRef} style={{ position: "relative", padding: 24 }}>
<motion.div
aria-hidden="true"
style={{
position: "sticky",
top: 0,
zIndex: 10,
height: 4,
scaleX: shouldReduceMotion ? 1 : scaleX,
transformOrigin: "0% 50%",
background: "#2563eb",
}}
/>
<motion.header
style={{
y: shouldReduceMotion ? 0 : y,
padding: "56px 0 32px",
}}
>
<p style={{ color: "#2563eb", fontWeight: 700 }}>
Claude Code x Motion
</p>
<h2 style={{ fontSize: 36, margin: 0 }}>
Halaman yang membuka konteks saat dibaca
</h2>
</motion.header>
<div style={{ display: "grid", gap: 24 }}>
{sections.map((section) => (
<section
key={section.title}
style={{
border: "1px solid #dbe4ee",
borderRadius: 12,
padding: 24,
background: "#ffffff",
}}
>
<h3>{section.title}</h3>
<p style={{ lineHeight: 1.8 }}>{section.body}</p>
</section>
))}
</div>
</article>
);
}
Pakai pola ini untuk orientasi, bukan untuk mengisi ruang kosong. Satu progress bar yang jelas biasanya lebih berguna daripada banyak scroll reveal yang membuat halaman terasa lambat.
Jadikan Claude Code reviewer
Setelah implementasi, minta review kritis dengan daftar failure mode.
Review diff saat ini sebagai implementasi Motion for React.
Periksa dengan ketat:
- Tidak mencampur `motion/react` dan import lama `framer-motion`
- Direct children dari `AnimatePresence` punya key stabil
- Reduced Motion mematikan gerakan besar, parallax, dan efek seperti autoplay
- Kode tidak sering menganimasikan width, height, top, atau left
- Manual test mengikuti aksi nyata user
Prompt ini membuat Claude Code bukan hanya generator, tetapi juga reviewer pertama. Karena bisa membaca file sekitar, ia dapat menemukan konflik CSS, perubahan state yang tidak diinginkan, dan test yang belum ada.
Pitfall dan checklist
Pitfall pertama adalah import lama. Pada legacy project, framer-motion bisa tetap benar, tetapi kode baru sebaiknya mengikuti motion dan motion/react kecuali repo memutuskan lain. Pitfall kedua adalah mengira exit rusak karena easing. Biasanya masalahnya ada di React tree: parent unmount terlalu cepat, key memakai index, atau item tidak keluar dari dalam AnimatePresence.
Pitfall ketiga adalah terlalu percaya pada layout. Fitur ini membantu reorder dan perubahan ukuran, tetapi image tanpa dimensi, font yang terlambat load, dan perubahan Grid mendadak masih bisa membuat elemen meloncat. Pitfall keempat adalah menunda aksesibilitas. Panduan resmi accessibility menjelaskan Reduced Motion; jika desain memakai gerakan besar, parallax, atau efek mirip autoplay, jalur alternatif harus ada sejak versi pertama.
Sebelum publish, pastikan: docs resmi dan import cocok, setiap animasi punya tujuan produk, Reduced Motion menghapus gerakan besar, children AnimatePresence memiliki key, keyboard dan focus tetap bekerja, dan efek scroll tidak mengganggu keterbacaan.
Untuk fondasi UI, baca Radix UI dengan Claude Code, shadcn/ui dengan Claude Code, dan panduan animasi Claude Code. Untuk agent-nya sendiri, lihat dokumentasi Claude Code dari Anthropic.
Kesimpulan
Menggabungkan Claude Code dan Framer Motion bukan hanya soal menulis animasi lebih cepat. Nilai utamanya adalah membawa implementasi, aksesibilitas, dan review criteria ke satu workflow sebelum UI dirilis.
Hasil praktik Masa cukup jelas: menulis motion/react, Reduced Motion, dan manual verification di prompt pertama mengurangi rework lebih banyak daripada polishing setelahnya. Untuk menyimpan template prompt, gunakan cheat sheet gratis. Jika ingin mereview beberapa layar bersama tim, halaman training dan konsultasi adalah langkah berikutnya yang realistis.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Permission safety ladder Claude Code: perluas akses tanpa kehilangan kontrol
Naik dari read-only ke edit terbatas, command bukti, dan cek deploy dengan kontrol yang jelas.
Claude Code Small PR Proof Pack: perubahan kecil yang mudah direview
Paket bukti untuk PR Claude Code: diff, check, URL publik, jalur CTA, dan rollback.
Review gate Claude Code sebelum commit: diff, test, URL publik, dan CTA
Cara memakai Claude Code sebelum commit: diff scope, build, URL publik, link Gumroad, CTA konsultasi, missing test, dan file tidak terkait.