FAQ Accordion

Frequently Asked Questions

We offer web design and development, branding, SEO, paid media, content strategy, and analytics. We also provide UX research, social media management, and marketing automation—all under one roof.

It depends on scope. A simple marketing site usually takes 6–10 weeks; a custom web app or e‑commerce build can run 3–6 months or more. We’ll outline phases and milestones in your proposal so you know what to expect.

Yes. We work with companies of all sizes—from early-stage startups to enterprises. We can scale our engagement to fit your budget, whether that’s a one-off brand or site or ongoing retainer work.

  • React
  • Typescript
  • GSAP
  • ScrollTrigger Plugin
  • useGSAP Plugin
  • Tailwind CSS
components/faq-accordion.tsx
import { useRef, useState } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SplitText } from "gsap/SplitText";

gsap.registerPlugin(useGSAP, ScrollTrigger);

export function FAQAccordion({
  items,
}: {
  items: { title: string; content: string }[];
}) {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAP(
    () => {
      // Animate dividers
      const dividerElements = containerRef.current?.querySelectorAll(
        "[data-element='divider']",
      );
      if (dividerElements && dividerElements.length > 0) {
        gsap.fromTo(
          dividerElements,
          {
            scaleX: 0,
            transformOrigin: "left center",
          },
          {
            delay: 0.5,
            scaleX: 1,
            duration: 0.75,
            ease: "power2.out",
            stagger: 0.1,
            scrollTrigger: {
              trigger: containerRef.current,
              start: "top 90%",
            },
          },
        );
      }

      // Animate titles
      const titleElements = containerRef.current?.querySelectorAll(
        "[data-element='title']",
      );
      if (titleElements && titleElements.length > 0) {
        const titleSplits = SplitText.create(titleElements, {
          type: "lines",
          mask: "lines",
        });

        gsap.fromTo(
          titleSplits.lines,
          {
            y: "100%",
          },
          {
            delay: 0.6,
            y: 0,
            duration: 0.75,
            ease: "power2.out",
            stagger: 0.1,
            scrollTrigger: {
              trigger: containerRef.current,
              start: "top 90%",
            },
          },
        );
      }

      // Animate icons
      const iconElements = containerRef.current?.querySelectorAll(
        "[data-element='icon']",
      );
      if (iconElements && iconElements.length > 0) {
        gsap.fromTo(
          iconElements,
          {
            opacity: 0,
          },
          {
            delay: 0.75,
            opacity: 1,
            duration: 1.2,
            ease: "power2.out",
            stagger: 0.1,
            scrollTrigger: {
              trigger: containerRef.current,
              start: "top 90%",
            },
          },
        );
      }
    },
    {
      scope: containerRef,
    },
  );

  return (
    <section ref={containerRef} className="w-full">
      {items.map((item, index) => (
        <FAQAccordionItem key={index} {...item} />
      ))}
    </section>
  );
}

export function FAQAccordionItem({
  title,
  content,
}: {
  title: string;
  content: string;
}) {
  const [open, setOpen] = useState(false);
  const contentRef = useRef<HTMLDivElement>(null);

  useGSAP(
    () => {
      const contentElement = contentRef.current;
      if (!contentElement) return;

      gsap.to(contentElement, {
        height: open ? "auto" : 0,
        duration: 0.4,
        ease: "power2.out",
        overflow: "hidden",
      });
    },
    { dependencies: [open] },
  );

  return (
    <div>
      <div className="h-px w-full bg-border" data-element="divider" />
      <button
        onClick={() => setOpen(!open)}
        className="group flex items-center justify-between w-full text-left cursor-pointer py-3 gap-4"
      >
        <p
          data-element="title"
          className={`text-lg tracking-tight transition-transform duration-300 ${!open ? "group-hover:translate-x-1" : "translate-x-0"}`}
        >
          {title}
        </p>
        <div data-element="icon" className="flex">
          <div
            className="h-3 w-0.5 bg-border transition-all duration-300"
            style={{ rotate: open ? "0deg" : "90deg", opacity: open ? 0 : 1 }}
          ></div>
          <div
            className="h-3 w-0.5 bg-border transition-all duration-300 -translate-x-0.5"
            style={{ rotate: open ? "-90deg" : "0deg" }}
          ></div>
        </div>
      </button>
      <div ref={contentRef} style={{ height: 0, overflow: "hidden" }}>
        <p className="pb-4">{content}</p>
      </div>
    </div>
  );
}

<FAQAccordion
  items={[
    {
      title: "What services do you offer?",
      content:
        "We offer web design and development, branding, SEO, paid media, content strategy, and analytics. We also provide UX research, social media management, and marketing automation—all under one roof.",
    },
    {
      title: "How long does a website project take?",
      content:
        "It depends on scope. A simple marketing site usually takes 6-10 weeks; a custom web app or e‑commerce build can run 3–6 months or more. We’ll outline phases and milestones in your proposal so you know what to expect.",
    },
    {
      title: "Do you work with startups and small businesses?",
      content:
        "Yes. We work with companies of all sizes—from early-stage startups to enterprises. We can scale our engagement to fit your budget, whether that’s a one-off brand or site or ongoing retainer work.",
    },
    {
      title: "What's included in a retainer?",
      content:
        "Our retainers include a set number of hours or deliverables each month—such as content updates, ads management, SEO, or ongoing design support. We’ll agree on scope, reporting cadence, and how we handle unused hours.",
    },
    {
      title: "How do you measure success?",
      content:
        "We agree on KPIs with you up front—traffic, conversions, revenue, engagement—and report on them regularly. We use your analytics and tools like Google Analytics, Search Console, and ad platforms to track and improve performance.",
    },
  ]}
/>

Frequently Asked Questions

We offer web design and development, branding, SEO, paid media, content strategy, and analytics. We also provide UX research, social media management, and marketing automation—all under one roof.

It depends on scope. A simple marketing site usually takes 6-10 weeks; a custom web app or e‑commerce build can run 3–6 months or more. We’ll outline phases and milestones in your proposal so you know what to expect.

Yes. We work with companies of all sizes—from early-stage startups to enterprises. We can scale our engagement to fit your budget, whether that’s a one-off brand or site or ongoing retainer work.

Our retainers include a set number of hours or deliverables each month—such as content updates, ads management, SEO, or ongoing design support. We’ll agree on scope, reporting cadence, and how we handle unused hours.

We agree on KPIs with you up front—traffic, conversions, revenue, engagement—and report on them regularly. We use your analytics and tools like Google Analytics, Search Console, and ad platforms to track and improve performance.