Flush Accordion
Original · freeA borderless, flush accordion separated by hairlines.
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/accordion-flush.json"use client";
import { useId, useRef, useState, type KeyboardEvent } from "react";
type FlushItem = {
question: string;
answer: string;
};
const ITEMS: FlushItem[] = [
{
question: "How long does a typical website build take?",
answer:
"Most marketing sites ship in three to five weeks. We lock scope in week one, design and build in parallel, then reserve the final week for QA, accessibility passes, and a staged launch you sign off on before it goes live.",
},
{
question: "Do you write the copy, or do we?",
answer:
"Either works. We can turn your rough notes into conversion-focused copy, or drop your existing text into a structure that actually guides visitors toward a decision. Most clients start with our draft and refine from there.",
},
{
question: "Will the site be fast and pass Core Web Vitals?",
answer:
"Yes. Every build targets green Core Web Vitals on mobile. We ship optimized images, minimal JavaScript, and system-font fallbacks so the first paint lands well under a second on a mid-range phone.",
},
{
question: "Can I edit the site myself after launch?",
answer:
"You get a lightweight editing setup and a short walkthrough recording. Change headlines, swap images, add case studies, or publish a blog post without touching code or waiting on us.",
},
{
question: "What happens if something breaks after we go live?",
answer:
"Every launch includes 30 days of support at no extra cost. After that you can stay on a monthly care plan for updates, backups, and priority fixes, or take full ownership of the codebase, no strings attached.",
},
];
function ChevronIcon({ open }: { open: boolean }) {
return (
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
className={
"h-5 w-5 shrink-0 text-slate-400 transition-transform duration-300 ease-out group-hover:text-indigo-500 dark:text-slate-500 dark:group-hover:text-indigo-400 " +
(open ? "-rotate-180" : "rotate-0")
}
>
<path d="m6 9 6 6 6-6" />
</svg>
);
}
export default function AccordionFlush() {
const [openIndex, setOpenIndex] = useState<number | null>(0);
const uid = useId();
const btnRefs = useRef<Array<HTMLButtonElement | null>>([]);
const toggle = (index: number) => {
setOpenIndex((current) => (current === index ? null : index));
};
const onKeyNav = (event: KeyboardEvent<HTMLButtonElement>, index: number) => {
const count = ITEMS.length;
let next: number | null = null;
if (event.key === "ArrowDown") next = (index + 1) % count;
else if (event.key === "ArrowUp") next = (index - 1 + count) % count;
else if (event.key === "Home") next = 0;
else if (event.key === "End") next = count - 1;
if (next !== null) {
event.preventDefault();
btnRefs.current[next]?.focus();
}
};
return (
<section className="relative w-full bg-white px-6 py-20 sm:py-28 dark:bg-slate-950">
<style>{`
@media (prefers-reduced-motion: reduce) {
.accflush_panel,
.accflush_inner { transition: none !important; }
}
`}</style>
<div className="mx-auto max-w-2xl">
<div className="mb-12 text-center">
<span className="inline-block rounded-full bg-indigo-50 px-3 py-1 text-xs font-semibold uppercase tracking-wider text-indigo-600 dark:bg-indigo-500/10 dark:text-indigo-300">
FAQ
</span>
<h2 className="mt-5 text-3xl font-semibold tracking-tight text-slate-900 sm:text-4xl dark:text-white">
Questions, answered
</h2>
<p className="mt-4 text-base leading-relaxed text-slate-500 dark:text-slate-400">
Everything you need to know before we start building. Still unsure?
Reach out and we’ll walk you through it.
</p>
</div>
<div className="divide-y divide-slate-200 border-y border-slate-200 dark:divide-slate-800 dark:border-slate-800">
{ITEMS.map((item, index) => {
const open = openIndex === index;
const headerId = `${uid}-h-${index}`;
const panelId = `${uid}-p-${index}`;
return (
<div key={item.question}>
<h3>
<button
type="button"
ref={(el) => {
btnRefs.current[index] = el;
}}
id={headerId}
aria-expanded={open}
aria-controls={panelId}
onClick={() => toggle(index)}
onKeyDown={(e) => onKeyNav(e, index)}
className="group flex w-full items-center justify-between gap-5 py-5 text-left outline-none transition-colors focus-visible:ring-2 focus-visible:ring-indigo-500/60 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-slate-950"
>
<span
className={
"text-base font-medium transition-colors sm:text-lg " +
(open
? "text-indigo-600 dark:text-indigo-400"
: "text-slate-800 group-hover:text-slate-950 dark:text-slate-200 dark:group-hover:text-white")
}
>
{item.question}
</span>
<ChevronIcon open={open} />
</button>
</h3>
<div
id={panelId}
role="region"
aria-labelledby={headerId}
className={
"accflush_panel grid transition-[grid-template-rows] duration-300 ease-out " +
(open ? "grid-rows-[1fr]" : "grid-rows-[0fr]")
}
>
<div className="overflow-hidden">
<p
className={
"accflush_inner pb-6 pr-8 text-[15px] leading-relaxed text-slate-600 transition-opacity duration-300 dark:text-slate-400 " +
(open ? "opacity-100" : "opacity-0")
}
>
{item.answer}
</p>
</div>
</div>
</div>
);
})}
</div>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Simple Accordion
OriginalA clean single-column accordion, one panel open at a time, chevron rotates.

Multi Accordion
OriginalAn accordion where multiple panels can be open at once.

Plus Minus Accordion
OriginalAccordion with a plus/minus icon that toggles per item.

Bordered Accordion
OriginalBordered card-style accordion panels with rounded corners.

Filled Accordion
OriginalFilled, tinted accordion panels; the active one is highlighted.

FAQ Two Col Accordion
OriginalA two-column FAQ accordion layout.

Numbered Accordion
OriginalA numbered-step accordion (01, 02, 03...).
Icon Left Accordion
OriginalAccordion with a leading icon per item and a right chevron.

Gradient Active Accordion
OriginalAccordion where the open panel gets a soft gradient background.

Nested Accordion
OriginalAn accordion with nested sub-accordions.

Pill Accordion
OriginalAccordion with rounded pill-shaped headers.

Dark Card Accordion
OriginalA dark, glassy card accordion.

