Smooth accordion
A question that opens smoothly to reveal its answer, with an arrow that turns as it expands.
Settings
Code
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { ChevronDown } from "lucide-react";
const spring = { type: "spring" as const, stiffness: 300, damping: 30 };
interface AccordionProps {
title?: string;
}
export default function Accordion({ title = "What’s included in the booking?" }: AccordionProps) {
const [open, setOpen] = useState(false);
return (
<div className="w-72 overflow-hidden rounded-[22px] bg-white dark:bg-[#1c1c1e] text-[#1d1d1f] dark:text-[#f5f5f7] shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_28px_rgba(0,0,0,0.05)]">
<button
type="button"
aria-expanded={open}
onClick={() => setOpen((o) => !o)}
className="flex w-full items-center justify-between p-5 text-left text-sm font-medium"
>
{title}
<motion.span animate={{ rotate: open ? 180 : 0 }} transition={spring}>
<ChevronDown className="h-4 w-4" />
</motion.span>
</button>
<AnimatePresence initial={false}>
{open && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={spring}
className="overflow-hidden"
>
<p className="border-t border-black/10 px-5 py-4 text-sm text-[#86868b] dark:border-white/10">
Everything you need is included. You can change this answer from the controls.
</p>
</motion.div>
)}
</AnimatePresence>
</div>
);
}
Prompt for AI
Paste it into ChatGPT, Claude or Cursor and it will adapt the block to your project with these settings, even if you don’t use React.
More in Microinteractions
Where to use it
Accordions keep FAQ pages and product details scannable: people read the questions and open only what they care about. Use it for “What does the booking include?” on a hotel site, shipping and returns in an online shop or the program of a course. The height animates instead of jumping, which makes this React accordion feel calm.
Write each question the way a customer would ask it, not as a heading like “Policies”. Keep answers to a short paragraph. If people usually need every answer, just show them on the page; hiding them only adds clicks.