---
name: shadcn-framer
description: ShadCN UI + Framer Motion patterns.
---
# ShadCN + Framer Motion
## ShadCN Setup
```bash
pnpm dlx shadcn@latest init
pnpm dlx shadcn@latest add button card dialog
```
## Component Usage
```typescript
import { Button } from '@/components/ui/button';
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from '@/components/ui/card';
export function UserCard({ user }: { user: User }) {
return (
{user.name}
{user.email}
{user.bio}
);
}
```
## Framer Motion Basics
```typescript
'use client';
import { motion } from 'framer-motion';
export function FadeIn({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
## Animated List
```typescript
'use client';
import { motion, AnimatePresence } from 'framer-motion';
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: { staggerChildren: 0.1 },
},
};
const item = {
hidden: { opacity: 0, x: -20 },
show: { opacity: 1, x: 0 },
};
export function AnimatedList({ items }: { items: Item[] }) {
return (
{items.map((i) => (
{i.name}
))}
);
}
```
## Page Transitions
```typescript
// components/page-transition.tsx
'use client';
import { motion } from 'framer-motion';
export function PageTransition({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
## Animated Dialog
```typescript
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
export function AnimatedDialog({
open,
onOpenChange,
children,
}: {
open: boolean;
onOpenChange: (open: boolean) => void;
children: React.ReactNode;
}) {
return (
);
}
```
## Hover Effects
```typescript
'use client';
import { motion } from 'framer-motion';
import { Card } from '@/components/ui/card';
export function HoverCard({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
## Loading Skeleton with Pulse
```typescript
'use client';
import { motion } from 'framer-motion';
export function Skeleton({ className }: { className?: string }) {
return (
);
}
```