Animated Background
Segmented control where the active pill slides smoothly via framer-motion layoutId shared layout animation.
Use and inspectUse this when the motion supports the surrounding content. Connect callbacks and state to your app, keep the reset preview as a local demonstration, and add a reduced-motion fallback for movement or looping. The preview is synthetic; it does not call a backend.Next: inspect the source below and replace the demo inputs with your own data.
Animated BackgroundSegmented control where the active pill slides smoothly via framer-motion layoutId shared layout animation.
"use client";
import { useState } from "react";
import { motion } from "framer-motion";
type AnimatedBackgroundItem = { id: string; label: string };
type AnimatedBackgroundProps = {
items: AnimatedBackgroundItem[];
defaultValue: string;
onChange?: (id: string) => void;
};
export function AnimatedBackground({ items, defaultValue, onChange }: AnimatedBackgroundProps) {
const [active, setActive] = useState(defaultValue);
function handleClick(id: string) {
setActive(id);
onChange?.(id);
}
return (
<div className="mp-animated-bg">
{items.map((item) => (
<button
key={item.id}
className={"mp-animated-bg-btn" + (active === item.id ? " mp-animated-bg-btn--active" : "")}
onClick={() => handleClick(item.id)}
>
{active === item.id && (
<motion.div
layoutId="mp-animated-bg-indicator"
className="mp-animated-bg-indicator"
transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>
)}
<span className="mp-animated-bg-label">{item.label}</span>
</button>
))}
</div>
);
}Install
npm install framer-motionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsrequired | { id: string; label: string }[] | — | Tab items |
| defaultValuerequired | string | — | Initially selected item id |
| onChange | (id: string) => void | — | Callback on selection change |