← FAQOpen in v0
FAQ 01 — Accordion
Centered accordion FAQ in a card with seven default questions and a contact link below.
$ npx shadcn@latest add @ludusvibe/faq-01Code
Installed to components/sections/faq-01.tsx — it's yours to edit.
"use client"
import * as React from "react"
import { ArrowRight } from "lucide-react"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import { Reveal } from "@/components/ludus/reveal"
import { cn } from "@/lib/utils"
export type Faq01Item = {
question: string
answer: React.ReactNode
}
export type Faq01Props = {
eyebrow?: string
title?: React.ReactNode
description?: string
items?: Faq01Item[]
/** Text before the contact link at the bottom. */
contactPrompt?: string
contactCta?: { label: string; href: string }
/** Heading element — use "h1" when this is the page's main heading. */
as?: "h1" | "h2"
className?: string
}
const defaultItems: Faq01Item[] = [
{
question: "How does the 14-day free trial work?",
answer:
"Every plan starts with a full-featured 14-day trial — no credit card required. You get everything in the plan you pick, and we'll remind you before the trial ends. If you don't upgrade, your account simply drops to read-only until you do.",
},
{
question: "Can I change plans later?",
answer:
"Yes. You can upgrade, downgrade or switch billing intervals at any time from your dashboard. Upgrades take effect immediately and we prorate the difference; downgrades apply at the start of your next billing cycle.",
},
{
question: "What counts as a monthly page view?",
answer:
"A page view is a single load of any page you publish with Lumen. We count unique loads, not visitors — a visitor browsing five pages counts as five views. Bot and crawler traffic is filtered out automatically and never counts against your quota.",
},
{
question: "Do you offer discounts for startups or nonprofits?",
answer:
"We do. Early-stage startups get 50% off Pro for their first year, and registered nonprofits and open-source projects get 30% off any plan, forever. Reach out from your work email and we'll set it up within a day.",
},
{
question: "How do you handle data privacy?",
answer:
"All data is encrypted in transit and at rest, and we're fully GDPR and CCPA compliant. On Pro and above you can choose EU-only data residency. We never sell or share your data — you can export or permanently delete everything at any time.",
},
{
question: "Can I cancel anytime?",
answer:
"Absolutely. Cancel in two clicks from your billing settings — no emails, no phone calls. Your plan stays active until the end of the period you've paid for, and you can export all of your data before or after cancelling.",
},
{
question: "What kind of support is included?",
answer:
"Starter includes community support with responses typically within a day. Pro adds priority email support with a 4-hour first-response target during business hours. Enterprise customers get a dedicated success manager and a shared Slack channel.",
},
]
export function Faq01({
eyebrow = "FAQ",
title = "Frequently asked questions",
description = "Everything you need to know about Lumen, billing and your data. Can't find what you're looking for? Our team is one message away.",
items = defaultItems,
contactPrompt = "Still have questions?",
contactCta = { label: "Talk to our team", href: "#" },
as: Heading = "h2",
className,
}: Faq01Props) {
return (
<section className={cn("bg-background px-6 py-24 md:py-32", className)}>
<div className="mx-auto max-w-3xl">
<div className="text-center">
<Reveal>
<p className="text-sm font-medium tracking-widest text-primary uppercase">
{eyebrow}
</p>
</Reveal>
<Reveal delay={0.1}>
<Heading className="mt-4 text-balance font-heading text-4xl font-semibold tracking-tight md:text-5xl">
{title}
</Heading>
</Reveal>
<Reveal delay={0.2}>
<p className="mx-auto mt-5 max-w-xl text-pretty text-muted-foreground md:text-lg">
{description}
</p>
</Reveal>
</div>
<Reveal delay={0.3} className="mt-12 md:mt-14">
<Accordion defaultValue={[0]} className="rounded-2xl border bg-card px-6">
{items.map((item, index) => (
<AccordionItem key={index} value={index}>
<AccordionTrigger className="py-5 text-base font-medium">
{item.question}
</AccordionTrigger>
<AccordionContent className="pb-5 text-base text-muted-foreground">
{item.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</Reveal>
<Reveal delay={0.4}>
<p className="mt-10 text-center text-sm text-muted-foreground">
{contactPrompt}{" "}
<a
href={contactCta.href}
className="inline-flex items-center gap-1 font-medium text-primary underline-offset-4 hover:underline"
>
{contactCta.label}
<ArrowRight className="size-3.5" />
</a>
</p>
</Reveal>
</div>
</section>
)
}