TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1"use client";2import * as React from "react";3import { AnimatePresence, motion, useReducedMotion } from "motion/react";4import { Plus } from "lucide-react";5import { cn } from "@/lib/utils";6import { Section, SectionHeading } from "./section";7import { Reveal } from "./reveal";8import { FAQ_ITEMS } from "./mock-data";910export function Faq() {11 const [open, setOpen] = React.useState<number | null>(0);12 const reduce = useReducedMotion();13 return (14 <Section id="faq" tone="subtle">15 <div className="grid gap-10 lg:grid-cols-12">16 <div className="lg:col-span-4">17 <SectionHeading eyebrow="FAQ" title="Questions, answered plainly" description="If yours isn't here, the privacy policy and terms are short and written for humans." />18 </div>19 <Reveal delay={0.1} className="lg:col-span-8">20 <ul className="divide-y divide-border rounded-xl border border-border bg-bg-elevated">21 {FAQ_ITEMS.map((item, i) => {22 const isOpen = open === i;23 const panelId = `faq-panel-${i}`;24 const btnId = `faq-button-${i}`;25 return (26 <li key={item.q}>27 <h3>28 <button29 id={btnId}30 type="button"31 aria-expanded={isOpen}32 aria-controls={panelId}33 onClick={() => setOpen(isOpen ? null : i)}34 className="flex w-full items-center justify-between gap-4 px-4 py-4 text-left text-[15px] font-medium transition-colors hover:bg-bg-subtle/60 sm:px-5"35 >36 <span>{item.q}</span>37 <Plus className={cn("size-4 shrink-0 text-fg-subtle transition-transform duration-200", isOpen && "rotate-45")} aria-hidden />38 </button>39 </h3>40 <AnimatePresence initial={false}>41 {isOpen ? (42 <motion.div43 id={panelId}44 role="region"45 aria-labelledby={btnId}46 key="panel"47 initial={reduce ? false : { height: 0, opacity: 0 }}48 animate={{ height: "auto", opacity: 1 }}49 exit={reduce ? undefined : { height: 0, opacity: 0 }}50 transition={{ duration: 0.24, ease: [0.16, 1, 0.3, 1] }}51 className="overflow-hidden"52 >53 <p className="px-4 pb-5 text-[14.5px] leading-7 text-fg-muted sm:px-5">{item.a}</p>54 </motion.div>55 ) : null}56 </AnimatePresence>57 </li>58 );59 })}60 </ul>61 </Reveal>62 </div>63 </Section>64 );65}66