# Faq 17

A shadcn/ui block from the [@diarmuradi](https://diarmuradi.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/diarmuradi/faq-17).

- Page, with a live preview: https://shadcn.exchange/r/diarmuradi/faq-17
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/diarmuradi/faq-17-light-0d6f6ffef47d3c46.png
- Registry item: https://diarmuradi.com/r/faq-17.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://diarmuradi.com/r/faq-17.json
```

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

## Dependencies

- npm packages: `@base-ui/react`
- Registry items: `https://diarmuradi.com/r/styles/base-nova/toggle-group.json`

## Files

### `faq.tsx`

```tsx
"use client"

import { useId, useState } from "react"
import { ToggleGroup } from "@base-ui/react/toggle-group"

import { ToggleGroupItem } from "@/components/ui/toggle-group"

type FaqItem = {
  value: string
  question: string
  answer: string
  label: string
}

const faqs: FaqItem[] = [
  {
    value: "item-1",
    label: "Slack",
    question: "Where do publish alerts go?",
    answer:
      "Map each project to a channel. The message includes the editor, the URL, and a diff of blocks that changed.",
  },
  {
    value: "item-2",
    label: "GitHub",
    question: "Can content sync to a repo?",
    answer:
      "Yes. Connect a repo and we open a pull request on every publish. Preview deploys use the same branch rules you already have.",
  },
  {
    value: "item-3",
    label: "Stripe",
    question: "How do paid pages unlock?",
    answer:
      "Attach a price to a page. After checkout succeeds, Stripe sends us the session and the visitor keeps access on that device.",
  },
  {
    value: "item-4",
    label: "Tokens",
    question: "What if an integration token expires?",
    answer:
      "We pause that integration and email the owner. Reconnect from Settings → Integrations. Queued events retry for 24 hours.",
  },
  {
    value: "item-5",
    label: "Webhooks",
    question: "Can I send events to my own URL?",
    answer:
      "Yes. Add an endpoint and pick the events. Failed deliveries retry for a day. You can replay any event from the log.",
  },
]

export function Faq() {
  const answerId = useId()
  const [activeValue, setActiveValue] = useState(faqs[0].value)
  const current = faqs.find((item) => item.value === activeValue) ?? faqs[0]

  return (
    <section
      aria-label="FAQ"
      className="mx-auto flex w-full max-w-4xl flex-col gap-6 text-foreground motion-reduce:**:animate-none motion-reduce:**:transition-none"
    >
      <header className="flex flex-col gap-3">
        <div className="flex flex-col gap-2">
          <h1 className="text-3xl font-semibold tracking-tight text-balance sm:text-4xl md:text-5xl">
            Integrations, as tiles
          </h1>
          <p className="text-muted-foreground">
            The large tile is the answer. The small ones switch it.
          </p>
        </div>
      </header>

      <div className="grid gap-3 md:grid-cols-3">
        {current ? (
          <article
            id={answerId}
            aria-live="polite"
            className="flex flex-col gap-3 rounded-2xl bg-card p-6 shadow-elevated-sm md:col-span-2 md:p-8"
          >
            <p className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
              {current.label}
            </p>
            <h2 className="text-2xl font-semibold tracking-tight">
              {current.question}
            </h2>
            <p className="text-muted-foreground">{current.answer}</p>
          </article>
        ) : null}
        <ToggleGroup
          aria-label="Integration questions"
          orientation="vertical"
          value={[activeValue]}
          onValueChange={(value) => {
            if (value[0]) setActiveValue(value[0])
          }}
          className="flex w-full flex-col gap-3"
        >
          {faqs.map((item) => (
            <ToggleGroupItem
              value={item.value}
              key={item.value}
              aria-controls={answerId}
              className="h-auto w-full flex-col items-start justify-start gap-2 rounded-2xl p-4 text-left font-normal whitespace-normal data-pressed:bg-muted data-pressed:text-foreground"
            >
              <span className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
                {item.label}
              </span>
              <span className="text-sm font-medium">{item.question}</span>
            </ToggleGroupItem>
          ))}
        </ToggleGroup>
      </div>
    </section>
  )
}
```
