faq.tsx
"use client"
import { useId, useState } from "react"
import { ToggleGroup } from "@base-ui/react/toggle-group"
import { ToggleGroupItem } from "@/components/ui/toggle-group"
import { FancyButton } from "@/components/ui/fancy-button"
type FaqItem = {
value: string
question: string
answer: string
label: string
}
const faqs: FaqItem[] = [
{
value: "item-1",
label: "Draft URL",
question: "How do I share a draft before the domain is ready?",
answer:
"Every workspace gets a private preview URL as soon as you save. Send that link to reviewers. Attaching a custom domain later does not change the published content or the comments already left on the draft.",
},
{
value: "item-2",
label: "Roles",
question: "Who can hit publish on day one?",
answer:
"The owner and anyone invited as Editor. Viewers can comment and request changes only. You can lock publishing from Settings → General until a launch checklist is complete.",
},
{
value: "item-3",
label: "Import",
question: "Can I bring copy from Notion or Google Docs?",
answer:
"Yes. Paste into a page or use Import. Headings become sections and images land in the asset library. You can undo the import as a single action if the structure looks wrong.",
},
{
value: "item-4",
label: "Sample",
question: "Is there a project I can duplicate?",
answer:
"Open the template gallery and duplicate “Launch example”. It ships with navigation, a form, and a blog index. Replace the copy; the structure stays.",
},
{
value: "item-5",
label: "Billing",
question: "When do I actually need a card?",
answer:
"Add billing before a third editor or a custom domain. Until then the starter workspace stays free and you can invite two teammates.",
},
]
export function Faq() {
const answerId = useId()
const [activeValue, setActiveValue] = useState(faqs[0].value)
const current = faqs.find((item) => item.value === activeValue) ?? faqs[0]
return (
<section
aria-label="FAQ"
className="mx-auto flex w-full max-w-3xl flex-col gap-8 text-foreground motion-reduce:**:animate-none motion-reduce:**:transition-none"
>
<header className="flex flex-col gap-3">
<p className="flex w-fit items-center gap-2 text-sm text-muted-foreground">
<span className="size-1.5 rounded-full bg-primary" />
Reader
</p>
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight text-balance sm:text-4xl md:text-5xl">
Read one answer
</h1>
<p className="text-muted-foreground">
An index on the left. The full answer stays on the right.
</p>
</div>
</header>
<div className="grid gap-8 md:grid-cols-[14rem_1fr]">
<ToggleGroup
aria-label="Questions"
orientation="vertical"
value={[activeValue]}
onValueChange={(value) => {
if (value[0]) setActiveValue(value[0])
}}
className="flex w-full flex-col gap-1"
>
{faqs.map((item, index) => (
<ToggleGroupItem
value={item.value}
key={item.value}
aria-controls={answerId}
className="h-auto w-full items-baseline justify-start gap-3 rounded-lg px-3 py-2 text-left font-normal whitespace-normal data-pressed:bg-muted data-pressed:text-foreground"
>
<span className="w-6 shrink-0 text-xs tabular-nums">
{String(index + 1).padStart(2, "0")}
</span>
<span className="text-sm font-medium">{item.label}</span>
</ToggleGroupItem>
))}
</ToggleGroup>
{current ? (
<article
id={answerId}
aria-live="polite"
className="flex flex-col gap-4 rounded-2xl bg-card p-6 shadow-elevated-sm md:min-h-80 md:p-8"
>
<p className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
{current.label}
</p>
<h2 className="text-2xl font-semibold tracking-tight">
{current.question}
</h2>
<p className="text-muted-foreground">{current.answer}</p>
<FancyButton size="lg" className="mt-auto w-fit">
Book a walkthrough
</FancyButton>
</article>
) : null}
</div>
</section>
)
}

























