faq.tsx
"use client"
import { useState } from "react"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import {
ToggleGroup,
ToggleGroupItem,
} from "@/components/ui/toggle-group"
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
type FaqItem = {
value: string
question: string
answer: string
}
type FaqCategoryValue = "General" | "Subscriptions" | "Services"
const faqsByCategory: Record<FaqCategoryValue, FaqItem[]> = {
General: [
{
value: "item-1",
question: "What services are included in the subscription?",
answer:
"Every plan includes unlimited design requests, a dedicated board, and two rounds of revision per task. Brand assets and source files are delivered with each request.",
},
{
value: "item-2",
question: "How many design requests can I make each month?",
answer:
"There is no request cap. Tasks are queued and worked one at a time so quality stays consistent. Pause or add requests whenever you need.",
},
{
value: "item-3",
question: "What is the turnaround time for design requests?",
answer:
"Smaller tasks such as graphics or copy tweaks take 2-4 hours. Larger pages and campaigns typically ship within one business day.",
},
],
Subscriptions: [
{
value: "item-4",
question: "Can I pause my subscription?",
answer:
"Pause anytime from billing. Your queue is saved, and you can resume on the same plan without setup fees.",
},
{
value: "item-5",
question: "What if I need services outside the subscription?",
answer:
"One-off projects such as motion or 3D can be quoted separately. We will share a fixed price before any work starts.",
},
],
Services: [
{
value: "item-6",
question: "Can I request revisions to the designs?",
answer:
"Yes. Each request includes two revision rounds. Extra rounds can be added as a follow-up task so nothing is blocked.",
},
{
value: "item-7",
question: "Who owns the final files?",
answer:
"You own everything we deliver. Source files, fonts we licensed for you, and exported assets are transferred at handoff.",
},
],
}
const categories = Object.keys(faqsByCategory) as FaqCategoryValue[]
export function Faq() {
const [activeCategory, setActiveCategory] =
useState<FaqCategoryValue>("General")
const faqs = faqsByCategory[activeCategory]
return (
<section
aria-label="FAQ"
className="mx-auto flex w-full max-w-2xl flex-col gap-8 text-foreground motion-reduce:**:animate-none motion-reduce:**:transition-none"
>
<header className="flex flex-col gap-3">
<p className="flex items-center gap-2 text-sm text-muted-foreground">
<span className="size-1.5 rounded-full bg-primary" />
Subscriptions
</p>
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight text-balance sm:text-4xl md:text-5xl">
Plans, seats, and renewals
</h1>
<p className="text-muted-foreground">
Use the rail to switch topics. Each question opens in place.
</p>
</div>
</header>
<div className="grid gap-8 md:grid-cols-[10rem_1fr]">
<ToggleGroup
value={[activeCategory]}
onValueChange={(value) => {
const category = categories.find(
(category) => category === value[0]
)
if (category) setActiveCategory(category)
}}
orientation="vertical"
spacing={1}
className="flex-row md:flex-col"
>
{categories.map((category) => (
<ToggleGroupItem
key={category}
value={category}
className="justify-start rounded-lg px-3 py-2 text-sm"
>
{category}
</ToggleGroupItem>
))}
</ToggleGroup>
<h2 className="sr-only">{activeCategory} questions</h2>
<Accordion
key={activeCategory}
defaultValue={faqs.slice(0, 1).map((item) => item.value)}
className="gap-2"
>
{faqs.map((item) => (
<AccordionItem
key={item.value}
value={item.value}
className="overflow-hidden rounded-xl border-0 bg-muted"
>
<AccordionTrigger className="p-4 text-left hover:no-underline *:data-[slot=accordion-trigger-icon]:hidden">
<span className="font-medium">{item.question}</span>
<span className="ml-auto flex size-7 shrink-0 items-center justify-center">
<ChevronDownIcon aria-hidden="true" className="size-3.5 text-muted-foreground group-aria-expanded/accordion-trigger:hidden" />
<ChevronUpIcon aria-hidden="true" className="hidden size-3.5 text-muted-foreground group-aria-expanded/accordion-trigger:inline" />
</span>
</AccordionTrigger>
<AccordionContent className="px-4 pb-4 text-sm text-muted-foreground">
{item.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</section>
)
}






























