components/we-inc/faq-accordion-with-plus-minus-icon.tsx
import { useState } from "react";
const faqs = [
{ q: "Can I bring a guest for the day?", a: "Members on the Resident plan can sign in two guests a day at the front desk. Guests get Wi-Fi, coffee and a hot desk, but not the phone booths." },
{ q: "Are the desks available at night?", a: "Fixed desks are open around the clock with your key fob. Hot desks and the kitchen close at 10pm so the cleaners can get in." },
{ q: "How does billing work if I pause?", a: "You can pause once a year for up to two months. We hold your locker and stop charging from the first of the next month." },
{ q: "Is there parking for bikes?", a: "There is a covered, locked bike room in the basement with forty stands, a pump and a shower next door." },
{ q: "Can I use the address for my company?", a: "Yes. Any paid plan includes a registered business address and post handling, with a photo of each letter sent the day it arrives." },
];
export default function FaqAccordionWithPlusMinusIcon() {
const [open, setOpen] = useState<Set<number>>(() => new Set([0]));
const toggle = (i: number) =>
setOpen((prev) => {
const next = new Set(prev);
if (next.has(i)) next.delete(i);
else next.add(i);
return next;
});
return (
<section className="fpm bg-slate-950 px-5 py-16 text-white sm:py-24">
<style>{`
.fpm-panel { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows .3s ease, opacity .3s ease; }
.fpm-panel[data-open] { grid-template-rows: 1fr; opacity: 1; }
.fpm-v { transition: transform .3s cubic-bezier(.2,.7,.2,1); transform-origin: center; }
[aria-expanded="true"] .fpm-v { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .fpm-panel, .fpm-v { transition: none; } }
`}</style>
<div className="mx-auto grid max-w-5xl gap-10 md:grid-cols-[1fr_1.6fr] md:gap-16">
<div>
<p className="text-sm font-medium text-sky-300">Ropewalk Studios</p>
<h2 className="mt-2 text-3xl font-semibold tracking-tight">Questions before you join</h2>
<p className="mt-4 text-[15px] leading-relaxed text-slate-400">Something else on your mind? Ask at the front desk or reply to your welcome email.</p>
</div>
<ul className="border-t border-white/10">
{faqs.map((f, i) => {
const isOpen = open.has(i);
return (
<li key={f.q} className="border-b border-white/10">
<h3>
<button
type="button"
id={`fpm-b${i}`}
aria-expanded={isOpen}
aria-controls={`fpm-p${i}`}
onClick={() => toggle(i)}
className="flex min-h-[60px] w-full items-center justify-between gap-6 py-5 text-left text-[17px] font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300 focus-visible:ring-offset-4 focus-visible:ring-offset-slate-950"
>
{f.q}
<span className={`grid h-8 w-8 shrink-0 place-items-center rounded-full border transition-colors ${isOpen ? "border-sky-300 bg-sky-300 text-slate-950" : "border-white/25 text-white"}`}>
<svg viewBox="0 0 16 16" className="h-3.5 w-3.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
<path d="M2 8h12" />
<path className="fpm-v" d="M8 2v12" />
</svg>
</span>
</button>
</h3>
<div id={`fpm-p${i}`} role="region" aria-labelledby={`fpm-b${i}`} data-open={isOpen ? "" : undefined} className="fpm-panel">
<div className="overflow-hidden" {...(isOpen ? {} : { inert: "" })}>
<p className="pb-6 pr-12 text-[15px] leading-relaxed text-slate-300">{f.a}</p>
</div>
</div>
</li>
);
})}
</ul>
</div>
</section>
);
}
