faq.tsx
"use client"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import { Badge } from "@/components/ui/badge"
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs"
import { CreditCardIcon, MailIcon, ShieldIcon, SparklesIcon, UserIcon } from 'lucide-react'
type FaqCategoryValue =
| "account"
| "billing"
| "support"
| "security"
| "features"
type FaqItem = {
value: string
question: string
answer: string
date: string
}
type FaqCategory = {
value: FaqCategoryValue
label: string
icon: React.ReactNode
}
const faqs: Record<FaqCategoryValue, FaqItem[]> = {
account: [
{
value: "a1",
question: "How do I create an account?",
answer:
"Click the 'Sign Up' button, enter your email, create a password, and verify your email address.",
date: "12 Jan, 2025",
},
{
value: "a2",
question: "Can I change my email address?",
answer: "Yes, you can update your email in account settings.",
date: "10 Jan, 2025",
},
{
value: "a3",
question: "How do I reset my password?",
answer:
"Click 'Forgot Password' on the login page and follow the emailed instructions.",
date: "09 Jan, 2025",
},
{
value: "a4",
question: "Can I delete my account?",
answer:
"Yes, you can request account deletion through the privacy dashboard.",
date: "07 Jan, 2025",
},
{
value: "a5",
question: "Can I have multiple accounts?",
answer:
"Our terms allow one personal account per user, but you can manage multiple organizations.",
date: "05 Jan, 2025",
},
],
billing: [
{
value: "b1",
question: "What payment methods do you accept?",
answer: "We accept all major credit cards, PayPal, and bank transfers.",
date: "08 Jan, 2025",
},
{
value: "b2",
question: "Do you offer refunds?",
answer: "We offer a 30-day money-back guarantee for new subscriptions.",
date: "04 Jan, 2025",
},
{
value: "b3",
question: "Can I change my plan anytime?",
answer:
"Yes, you can upgrade or downgrade in settings; changes are prorated.",
date: "02 Jan, 2025",
},
],
support: [
{
value: "s1",
question: "How do I contact support?",
answer:
"Our support team is available 24/7 via live chat, email, and phone.",
date: "03 Jan, 2025",
},
{
value: "s2",
question: "How long does response take?",
answer: "We typically respond within 1-2 hours during business hours.",
date: "01 Jan, 2025",
},
{
value: "s3",
question: "Do you have a knowledge base?",
answer:
"Yes, our comprehensive help center is available at help.example.com.",
date: "29 Dec, 2024",
},
{
value: "s4",
question: "Is phone support available for all plans?",
answer: "Priority phone support is available for Business customers.",
date: "27 Dec, 2024",
},
],
security: [
{
value: "sec1",
question: "How secure is my data?",
answer:
"We use bank-level encryption and comply with GDPR and SOC 2 standards.",
date: "28 Dec, 2024",
},
{
value: "sec2",
question: "Is my data backed up?",
answer:
"Yes, data is backed up multiple times daily across distributed servers.",
date: "25 Dec, 2024",
},
{
value: "sec3",
question: "Can I enable 2FA?",
answer:
"Yes, you can enable Two-Factor Authentication in your security settings.",
date: "22 Dec, 2024",
},
],
features: [
{
value: "f1",
question: "What are the main features?",
answer:
"Real-time collaboration, advanced analytics, and custom integrations.",
date: "22 Dec, 2024",
},
{
value: "f2",
question: "Do you have an API?",
answer: "Yes, we offer a full REST API for custom software integrations.",
date: "20 Dec, 2024",
},
],
}
const categories: FaqCategory[] = [
{
label: "Account",
value: "account",
icon: (
<UserIcon aria-hidden="true" className="size-4 group-data-active:text-primary" />
),
},
{
label: "Billing",
value: "billing",
icon: (
<CreditCardIcon aria-hidden="true" className="size-4 group-data-active:text-primary" />
),
},
{
label: "Support",
value: "support",
icon: (
<MailIcon aria-hidden="true" className="size-4 group-data-active:text-primary" />
),
},
{
label: "Security",
value: "security",
icon: (
<ShieldIcon aria-hidden="true" className="size-4 group-data-active:text-primary" />
),
},
{
label: "Features",
value: "features",
icon: (
<SparklesIcon aria-hidden="true" className="size-4 group-data-active:text-primary" />
),
},
]
export function Faq() {
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">
<Badge variant="secondary" className="w-fit">
Browse topics
</Badge>
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight text-balance sm:text-4xl md:text-5xl">
Answers by category
</h1>
<p className="text-muted-foreground">
Jump to billing, security, or features without leaving the page.
</p>
</div>
</header>
<Tabs defaultValue="account" className="w-full">
<TabsList className="grid h-auto w-full grid-cols-5 gap-2 rounded-full px-1">
{categories.map(({ value, label, icon }) => (
<TabsTrigger
key={value}
value={value}
aria-label={label}
className="group flex items-center gap-2 rounded-full border-0 py-2 data-active:bg-background group-data-[variant=default]/tabs-list:data-active:shadow-elevated-xs!"
>
{icon}
<span className="inline max-sm:hidden">{label}</span>
</TabsTrigger>
))}
</TabsList>
{categories.map(({ value, label }) => (
<TabsContent key={value} value={value} className="mt-6">
<h2 className="sr-only">{label} questions</h2>
<Accordion
className="gap-2"
defaultValue={faqs[value].slice(0, 1).map((item) => item.value)}
>
{faqs[value].map((item) => (
<AccordionItem
key={item.value}
value={item.value}
className="overflow-hidden rounded-xl border-0 bg-muted"
>
<AccordionTrigger className="px-4 text-muted-foreground hover:text-foreground hover:no-underline aria-expanded:text-foreground">
{item.question}
</AccordionTrigger>
<AccordionContent className="flex flex-col gap-2 px-4 pb-4 text-muted-foreground">
<p className="text-sm leading-relaxed">{item.answer}</p>
{item.date && (
<time className="text-xs text-muted-foreground/60">
{item.date}
</time>
)}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</TabsContent>
))}
</Tabs>
</section>
)
}