{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "faq",
  "type": "registry:ui",
  "title": "Faq",
  "description": "Frequently-asked-questions accordion. Composes the canonical Accordion primitive into a single-prop API: pass an array of {question, answer} and get the full disclosure pattern (keyboard, ARIA, animation) inherited from Accordion → Base UI.",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "marketing",
    "pattern"
  ],
  "dependencies": [],
  "registryDependencies": [
    "https://ds.interlace.tools/r/theme.json",
    "https://ds.interlace.tools/r/accordion.json",
    "https://ds.interlace.tools/r/cn.json",
    "https://ds.interlace.tools/r/container.json",
    "https://ds.interlace.tools/r/skeleton.json",
    "https://ds.interlace.tools/r/stack.json",
    "https://ds.interlace.tools/r/typography.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/patterns/faq.tsx",
      "target": "components/ui/patterns/faq.tsx",
      "type": "registry:ui",
      "content": "'use client';\n\nimport * as React from 'react';\n\n// @interlace/faq v1.0.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/faq\n// What changed since: https://ds.interlace.tools/c/faq#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — FAQ\n *\n * Frequently-asked-questions accordion. Composes the canonical Accordion\n * primitive into a single-prop API: pass an array of {question, answer}\n * and get the full disclosure pattern (keyboard, ARIA, animation)\n * inherited from Accordion → Base UI.\n *\n * ## Anatomy\n *\n *   <section data-slot=\"faq\" data-min-viewport=\"320\">\n *     <Container>\n *       <Typography variant=\"h2\">{title}</Typography>\n *       <Accordion>{questions.map(...)}</Accordion>\n *     </Container>\n *   </section>\n *\n * | Rule | Concept                          | Where in this file                                          |\n * | ---- | -------------------------------- | ----------------------------------------------------------- |\n * | R4   | Extends native el                | `React.ComponentProps<'section'>` + FAQ props               |\n * | R6   | data-slot on root                | `data-slot=\"faq\"`                                           |\n * | R10  | Composition seam (questions)     | Array<{question, answer}>                                    |\n * | R14  | Declares min viewport            | `data-min-viewport={String(MIN_VIEWPORT)}` + exported const |\n * | R18  | Tailwind only                    | Zero inline `style`                                         |\n * | R19  | Tokens only                      | Container + Accordion own all tokens                        |\n * | R25  | Client component                 | Accordion is client-tier                                    |\n * | R26  | A11y from Accordion              | Accordion owns disclosure ARIA                              |\n */\n\nimport { cn } from '@/lib/utils';\nimport {\n  Accordion,\n  AccordionItem,\n  AccordionTrigger,\n  AccordionContent,\n} from '@/components/ui/accordion';\nimport { Container } from '@/components/ui/container';\nimport { Skeleton } from '@/components/ui/skeleton';\nimport { Stack } from '@/components/ui/stack';\nimport { Typography } from '@/components/ui/typography';\n\nexport const MIN_VIEWPORT = 320 as const;\n\ninterface FAQItem {\n  question: React.ReactNode;\n  answer: React.ReactNode;\n}\n\ninterface FAQProps extends Omit<React.ComponentProps<'section'>, 'title'> {\n  title?: React.ReactNode;\n  lead?: React.ReactNode;\n  items?: FAQItem[];\n  /**\n   * Whether more than one item can be open at a time. Defaults to\n   * `false` (single-open).\n   */\n  multiple?: boolean;\n  /** When true, render a placeholder list of card skeletons. */\n  loading?: boolean;\n  /** Skeleton count when loading. Defaults to 4. */\n  loadingCount?: number;\n}\n\nfunction FAQ({\n  title,\n  lead,\n  items = [],\n  multiple = false,\n  loading,\n  loadingCount = 4,\n  className,\n  ...props\n}: FAQProps) {\n  return (\n    <section\n      data-slot=\"faq\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      className={cn('py-xl', className)}\n      {...props}\n    >\n      <Container size=\"prose\">\n        <Stack gap=\"lg\">\n          {(title || lead) && (\n            <Stack gap=\"sm\">\n              {title ? (\n                <Typography variant=\"h2\" as=\"h2\" className=\"text-balance\">\n                  {title}\n                </Typography>\n              ) : null}\n              {lead ? (\n                <Typography variant=\"long\" tone=\"muted\">\n                  {lead}\n                </Typography>\n              ) : null}\n            </Stack>\n          )}\n          {loading ? (\n            <Stack gap=\"sm\">\n              {Array.from({ length: loadingCount }).map((_, i) => (\n                <Skeleton key={i} variant=\"card\" label={null} />\n              ))}\n            </Stack>\n          ) : items.length > 0 ? (\n            <Accordion multiple={multiple}>\n              {items.map((item, i) => (\n                <AccordionItem key={i} value={`faq-${i}`}>\n                  <AccordionTrigger>{item.question}</AccordionTrigger>\n                  <AccordionContent>{item.answer}</AccordionContent>\n                </AccordionItem>\n              ))}\n            </Accordion>\n          ) : null}\n        </Stack>\n      </Container>\n    </section>\n  );\n}\nFAQ.displayName = 'FAQ';\n\nexport { FAQ };\nexport type { FAQProps, FAQItem };\n"
    }
  ],
  "meta": {
    "tier": "pattern",
    "client": true,
    "minViewport": 320,
    "loading": true,
    "version": "1.0.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/faq\n\nInstalled to `components/ui/patterns/faq.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/patterns/faq';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/faq\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
