# FAQs Block

> A FAQs Block component for displaying frequently asked questions.

A shadcn/ui block from the [@devsloka](https://ui.devsloka.in/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/devsloka/faqs-block).

- Page, with a live preview: https://shadcn.exchange/r/devsloka/faqs-block
- Screenshot: https://shadcn.exchange/shot/devsloka/faqs-block/light.png
- Registry item: https://ui.devsloka.in/r/faqs-block.json
- Listed: 2026-10-28, source last changed 2026-10-28

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/devsloka/faqs-block.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `accordion`

## Files

### `src/registry/blocks/faqs-block.tsx`

```tsx
import type { ComponentProps } from "react";

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { cn } from "@/lib/utils";

export type FAQ = {
  question: string;
  answer: string;
};

export type FAQsBlockProps = {
  eyebrow?: string;
  title?: string;
  note?: string;
  supportEmail?: string;
  lastUpdated?: string;
  faqs?: FAQ[];
} & ComponentProps<"section">;

const DEFAULT_FAQS: FAQ[] = [
  {
    question: "Can I send invoices in more than one currency?",
    answer:
      "Yes. Ledgerline supports 41 currencies. Each client has a default currency, and you can override it on any single invoice. Exchange rates are taken from the European Central Bank at 16:00 CET on the issue date and printed in the invoice footer.",
  },
  {
    question: "What happens when a client pays late?",
    answer:
      "Nothing, unless you ask for it. You can turn on reminders at 3, 7 and 14 days past due, and optionally add a late fee as a fixed amount or a monthly percentage. Reminders come from your own address, not ours.",
  },
  {
    question: "Do you take a cut of card payments?",
    answer:
      "No. Card payments go through your own Stripe or Adyen account and you pay their standard rates. Ledgerline charges a flat monthly fee: €12 for Solo, €29 for Studio with up to five seats.",
  },
  {
    question: "Can my accountant get access without a paid seat?",
    answer:
      "Yes. Invite them as an Accountant from Settings → People. They can read every invoice and export VAT reports, but cannot create, edit or delete anything. Accountant seats are free and unlimited.",
  },
  {
    question: "How do I move my data out if I leave?",
    answer:
      "Settings → Export gives you a ZIP with every invoice as a PDF plus a CSV of clients, line items and payments. It is available on every plan, including after cancellation, for 90 days.",
  },
  {
    question: "Is there a limit on the number of clients or invoices?",
    answer:
      "No limits on either. The only cap is file storage for attachments: 5 GB on Solo and 50 GB on Studio. Invoice PDFs themselves don't count towards it.",
  },
];

export default function FAQsBlock({
  eyebrow = "Questions",
  title = "Things people ask before they switch",
  note = "Most of these come from the first week of a trial. If yours isn't here, it's probably a good one.",
  supportEmail = "support@ledgerline.app",
  lastUpdated = "Updated 2 Sep 2026",
  faqs = DEFAULT_FAQS,
  className,
  ...props
}: FAQsBlockProps) {
  return (
    <section
      data-slot="faqs-block"
      aria-labelledby="faqs-block-title"
      className={cn("bg-background text-foreground w-full", className)}
      {...props}
    >
      <div className="mx-auto grid max-w-6xl gap-12 px-6 py-20 md:grid-cols-12 md:gap-8 md:py-28">
        <div className="md:col-span-5">
          <div className="md:sticky md:top-24">
            <p className="text-muted-foreground font-mono text-xs tracking-wider uppercase">
              {eyebrow}
            </p>
            <h2
              id="faqs-block-title"
              className="mt-4 max-w-sm text-3xl font-semibold tracking-tight text-balance md:text-4xl"
            >
              {title}
            </h2>
            <p className="text-muted-foreground mt-5 max-w-sm text-sm leading-relaxed">
              {note}
            </p>
            <div className="mt-10 border-t pt-5 text-sm">
              <p className="text-muted-foreground">Still stuck?</p>
              <p className="mt-1">
                Write to{" "}
                <a
                  href={`mailto:${supportEmail}`}
                  className="decoration-primary font-medium underline underline-offset-4 outline-none hover:decoration-2 focus-visible:ring-2 focus-visible:ring-ring"
                >
                  {supportEmail}
                </a>
                . A person reads every message.
              </p>
            </div>
            <p className="text-muted-foreground mt-6 font-mono text-[11px] tracking-wider uppercase">
              {lastUpdated}
            </p>
          </div>
        </div>

        <div className="md:col-span-7">
          <Accordion type="single" collapsible className="border-t">
            {faqs.map((faq, index) => (
              <AccordionItem
                key={faq.question}
                value={`item-${index}`}
                className="border-b last:border-b"
              >
                <AccordionTrigger className="group gap-6 rounded-none py-6 text-base font-medium hover:no-underline md:text-lg">
                  <span className="flex items-baseline gap-5">
                    <span
                      aria-hidden="true"
                      className="text-muted-foreground group-data-[state=open]:text-primary font-mono text-xs tabular-nums"
                    >
                      {String(index + 1).padStart(2, "0")}
                    </span>
                    <span className="decoration-muted-foreground/40 underline-offset-4 group-hover:underline">
                      {faq.question}
                    </span>
                  </span>
                </AccordionTrigger>
                <AccordionContent className="text-muted-foreground max-w-prose pb-7 pl-10 text-[15px] leading-relaxed">
                  {faq.answer}
                </AccordionContent>
              </AccordionItem>
            ))}
          </Accordion>
        </div>
      </div>
    </section>
  );
}

export { FAQsBlock };
```
