62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Faq — accessible accordion built on real <button> controls with
|
|
* aria-expanded / aria-controls and a CSS grid-rows reveal (no JS height math,
|
|
* animates cleanly, collapsible content stays in the DOM for SEO/AEO). The
|
|
* answer copy matches the FAQPage JSON-LD in layout.tsx verbatim.
|
|
*/
|
|
|
|
import { useState } from "react";
|
|
import Reveal from "./Reveal";
|
|
import { faqs } from "../content";
|
|
|
|
export default function Faq() {
|
|
const [open, setOpen] = useState<number | null>(0);
|
|
|
|
return (
|
|
<section id="faq" className="faq" aria-label="Frequently asked questions">
|
|
<div className="wrap faq__inner">
|
|
<div className="faq__head">
|
|
<p className="kicker">FAQ</p>
|
|
<h2 className="section__title">
|
|
Questions about working with a digital marketing agency
|
|
</h2>
|
|
</div>
|
|
|
|
<div className="faq__list">
|
|
{faqs.map((f, i) => {
|
|
const isOpen = open === i;
|
|
return (
|
|
<div className="faq__item" key={f.q} data-open={isOpen}>
|
|
<h3>
|
|
<button
|
|
type="button"
|
|
className="faq__q hoverable"
|
|
aria-expanded={isOpen}
|
|
aria-controls={`faq-a-${i}`}
|
|
id={`faq-q-${i}`}
|
|
onClick={() => setOpen(isOpen ? null : i)}
|
|
>
|
|
{f.q}
|
|
<span className="faq__icon" aria-hidden="true" />
|
|
</button>
|
|
</h3>
|
|
<div
|
|
className="faq__a"
|
|
id={`faq-a-${i}`}
|
|
role="region"
|
|
aria-labelledby={`faq-q-${i}`}
|
|
>
|
|
<div className="faq__a-inner">
|
|
<p>{f.a}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|