hexui
blockfaq-2source: ok · hit
Faq-2
A simple and professional FAQ section with categorized collapsible questions and answers
npx shadcn add "https://hexui.sh/r/faq-2.json"free
Where it goes
faq
Interaction
accordion
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightRegistry dependencies
avatarbuttonaccordion
Files3 · source cached 10/9/2026, 10:19:05 PM
registry/blocks/faq/faq-2/source/app/faq/page.tsx
import { FAQ } from "../../components/faq"
export default function Page() {
return (
<div className="flex min-h-screen w-full flex-col items-center px-6 py-4">
<FAQ />
</div>
)
}
registry/blocks/faq/faq-2/source/components/faq.tsx
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
import { SupportContactCard, type SupportAvatar } from "./support-contact-card"
type FAQItem = {
value: string
question: string
answer: string
}
// FAQs grouped by category; each category renders its own Accordion section.
type FAQCategory = {
title: string
items: FAQItem[]
}
const faqCategories: FAQCategory[] = [
{
title: "Account & Collaboration",
items: [
{
value: "account",
question: "How do I create an account?",
answer:
"You can sign up using your email address or a supported social login. Once registered, your workspace will be created automatically and you can start adding pages immediately.",
},
{
value: "collaboration",
question: "Can I collaborate with my team in real time?",
answer:
"Yes, multiple users can edit the same page simultaneously. Changes are synced instantly, and you can leave comments, mention teammates, and track updates in real time.",
},
{
value: "offline",
question: "Does the app work offline?",
answer:
"You can view and edit recently opened pages without an internet connection. Your changes will automatically sync once you reconnect.",
},
],
},
{
title: "Security & Data",
items: [
{
value: "security",
question: "How is my data secured?",
answer:
"All data is encrypted in transit and at rest. We follow industry-standard security practices and regularly perform backups to ensure your content is protected.",
},
{
value: "storage",
question: "Is there a storage limit?",
answer:
"Free plans include a limited storage quota, while paid plans offer higher or unlimited storage depending on the subscription tier.",
},
],
},
{
title: "Billing",
items: [
{
value: "billing",
question: "How does billing work?",
answer:
"Billing is based on your selected plan and the number of active users in your workspace. You can upgrade, downgrade, or cancel your subscription at any time from the billing settings.",
},
],
},
]
// Support team avatars; `className` z-indexes control their overlap order in AvatarGroup.
const supportAvatars: ReadonlyArray<SupportAvatar> = [
{
src: "/demo/avatars/avatar-1.svg",
alt: "@u1",
fallback: "A1",
className: "z-1",
},
{
src: "https://avatars.githubusercontent.com/u/114809507",
alt: "@ri0n_dev",
fallback: "RI",
className: "z-2",
},
{
src: "/demo/avatars/avatar-4.svg",
alt: "@u2",
fallback: "A4",
className: "z-1",
},
]
export function FAQ() {
return (
<section className="relative flex w-full justify-center py-16">
<div className="flex w-full max-w-3xl flex-col items-center gap-10">
<div className="flex flex-col gap-2 text-center">
<p className="text-pretty text-sm leading-relaxed text-muted-foreground">
FAQ
</p>
<h1 className="text-balance text-2xl font-semibold tracking-tight md:text-3xl xl:text-4xl">
Your Questions Answered
</h1>
<p className="mt-2 text-muted-foreground">
Need help with something? Here are some of the most common questions
we get.
</p>
</div>
<div className="flex w-full max-w-2xl flex-col gap-8">
{faqCategories.map((category) => (
<div key={category.title} className="flex flex-col gap-2">
<h2 className="text-sm font-semibold tracking-wide text-foreground/80 md:text-base">
{category.title}
</h2>
<Accordion>
{category.items.map((item) => (
<AccordionItem key={item.value} value={item.value}>
<AccordionTrigger className="md:text-base">
{item.question}
</AccordionTrigger>
<AccordionContent className="md:text-base leading-relaxed text-muted-foreground/90">
{item.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
))}
</div>
<SupportContactCard supportAvatars={supportAvatars} />
</div>
</section>
)
}
registry/blocks/faq/faq-2/source/components/support-contact-card.tsx
import {
Avatar,
AvatarFallback,
AvatarGroup,
AvatarImage,
} from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
export type SupportAvatar = {
src: string
alt: string
fallback: string
className: string
}
type SupportContactCardProps = {
supportAvatars: ReadonlyArray<SupportAvatar>
}
export function SupportContactCard({ supportAvatars }: SupportContactCardProps) {
return (
<div className="flex w-full flex-col items-center rounded-lg border px-4 py-14">
<div className="flex max-w-lg flex-col items-center gap-5">
{/* `grayscale` mutes the avatars so the CTA button remains the visual focus. */}
<AvatarGroup className="grayscale">
{supportAvatars.map((avatar) => (
<Avatar
key={avatar.src}
size="lg"
className={cn("border bg-accent", avatar.className)}
>
<AvatarImage src={avatar.src} alt={avatar.alt} />
<AvatarFallback>{avatar.fallback}</AvatarFallback>
</Avatar>
))}
</AvatarGroup>
<div className="flex flex-col gap-2 text-center">
<h2 className="font-semibold md:text-2xl">Still have questions?</h2>
<p className="text-muted-foreground">
If you can’t find the answer you’re looking for, please
chat to our support team.
</p>
</div>
<Button size="lg">Get in touch</Button>
</div>
</div>
)
}