"use client"; import { useLayoutEffect, useRef, useState, type CSSProperties } from "react"; import "./focus-faq.css"; /** * Focus FAQ * Instead of rows opening in place, the question you pick becomes the page's * subject. Every question is a FLIP element: we record where each one is, * change the layout, then animate each from its old box to its new one — so * the chosen question visibly travels up and grows into the heading while the * others slide into a smaller list underneath. */ export type QA = { q: string; a: string }; type Props = { items: QA[]; title?: string; accent?: string; className?: string }; export function FocusFaq({ items, title = "Questions, answered", accent = "#e8a24a", className = "" }: Props) { const [active, setActive] = useState(null); const root = useRef(null); const before = useRef>(new Map()); const snapshot = () => { before.current = new Map(Array.from(root.current!.querySelectorAll("[data-flip]")).map((el) => [el.dataset.flip!, el.getBoundingClientRect()])); }; const choose = (i: number | null) => { snapshot(); setActive(i); }; useLayoutEffect(() => { if (!before.current.size || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; root.current!.querySelectorAll("[data-flip]").forEach((el) => { const a = before.current.get(el.dataset.flip!); if (!a) return; const b = el.getBoundingClientRect(); const dx = a.left - b.left, dy = a.top - b.top, s = a.height / b.height; if (Math.abs(dx) < 1 && Math.abs(dy) < 1 && Math.abs(s - 1) < 0.01) return; el.animate( [{ transformOrigin: "0 0", transform: `translate(${dx}px, ${dy}px) scale(${s})` }, { transformOrigin: "0 0", transform: "none" }], { duration: 620, easing: "cubic-bezier(0.16, 1, 0.3, 1)" }, ); }); before.current.clear(); }, [active]); const rest = items.map((it, i) => ({ it, i })).filter(({ i }) => i !== active); return (

{active === null ? title : `Question ${String(active + 1).padStart(2, "0")} of ${String(items.length).padStart(2, "0")}`}

{active !== null && (

{items[active].q}

{items[active].a}

)}
    {rest.map(({ it, i }) => (
  1. ))}
); }