{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "faq-section",
  "type": "registry:block",
  "title": "FAQ section",
  "description": "FAQs as an accordion, a topic rail, or a searchable list that highlights matches.",
  "categories": [
    "blocks"
  ],
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://irisui.dev/r/foundation.json",
    "https://irisui.dev/r/search-field.json",
    "https://irisui.dev/r/segmented-control.json",
    "https://irisui.dev/r/motion-tokens.json",
    "https://irisui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/registry/blocks/faq-section/faq-section.tsx",
      "content": "\"use client\";\n\nimport { forwardRef, useId, useMemo, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport { AnimatePresence, LayoutGroup, motion, useReducedMotion } from \"motion/react\";\nimport type { Variants } from \"motion/react\";\nimport { ArrowRight, Plus } from \"lucide-react\";\nimport { SearchField } from \"../../search-field/search-field\";\nimport SegmentedControl from \"../../segmented-control/segmented-control\";\nimport { motionTokens } from \"../../lib/motion-tokens\";\nimport { cn } from \"../../lib/utils\";\n\nexport type FaqSectionVariant = \"accordion\" | \"columns\" | \"search\";\n\nexport interface FaqItem {\n  /** Stable id used for open state. Defaults to the question. */\n  id?: string;\n  question: string;\n  /** Plain text answer; it is also what search matches. */\n  answer: string;\n  /** Groups questions in the columns variant. */\n  category?: string;\n}\n\nexport interface FaqSectionProps {\n  /** `accordion` is one centered list, `columns` groups questions beside a category rail, `search` filters as you type. */\n  variant?: FaqSectionVariant;\n  title?: string;\n  description?: string;\n  items?: FaqItem[];\n  /** Allow several answers open at once. Defaults to false. */\n  multiple?: boolean;\n  /** Open item ids (controlled). */\n  value?: string[];\n  /** Initially open item ids when uncontrolled. */\n  defaultValue?: string[];\n  onValueChange?: (value: string[]) => void;\n  /** Active category in the columns variant (controlled). */\n  category?: string;\n  onCategoryChange?: (category: string) => void;\n  /** Search text in the search variant (controlled). */\n  query?: string;\n  onQueryChange?: (query: string) => void;\n  /** A way to reach a person when the answer isn't here. Pass null to hide it. */\n  contact?: { label: string; description?: string; href?: string; onClick?: () => void } | null;\n  className?: string;\n}\n\ntype Bezier = [number, number, number, number];\nconst enter = [...motionTokens.ease.enter] as Bezier;\nconst standard = [...motionTokens.ease.standard] as Bezier;\nconst { duration } = motionTokens;\n\n/** Sample questions about Polaris, which drafts marketing copy from what a team has approved. */\nexport const faqExampleItems: FaqItem[] = [\n  {\n    question: \"What is Polaris?\",\n    answer:\n      \"Polaris writes from what your team has approved, flags any claim your material can't back, and takes the piece through review, scheduling and publishing.\",\n    category: \"Product\",\n  },\n  {\n    question: \"Which languages does it write in?\",\n    answer: \"English and Greek. Each brand in a workspace keeps its own voice profile, brand facts and documents.\",\n    category: \"Product\",\n  },\n  {\n    question: \"What is a voice score?\",\n    answer: \"A score for how close a draft sits to your voice profile. A draft needs at least 70 before it moves on.\",\n    category: \"Product\",\n  },\n  {\n    question: \"Where can Polaris publish?\",\n    answer: \"WordPress, LinkedIn, X and Facebook, through the accounts you connect to the workspace.\",\n    category: \"Publishing\",\n  },\n  {\n    question: \"What happens when a publish fails?\",\n    answer: \"Polaris tries up to 3 times, then marks the piece as failed so someone on the team can look at it.\",\n    category: \"Publishing\",\n  },\n  {\n    question: \"Who approves a draft?\",\n    answer:\n      \"Your approval workflow. A reviewer can approve the draft, reject it or request changes before it is scheduled.\",\n    category: \"Publishing\",\n  },\n  {\n    question: \"Is there a free plan?\",\n    answer: \"Yes. Free includes 50 generations every 30 days, 2 seats and 1 connected account.\",\n    category: \"Plans\",\n  },\n  {\n    question: \"What does Pro add?\",\n    answer: \"1,000 generations, 10 seats and 10 connected accounts. Scale removes the generation limit.\",\n    category: \"Plans\",\n  },\n];\n\n/** The single column layouts (accordion and search) share one centered stack. */\nconst stack = \"mx-auto grid max-w-[720px] gap-8 px-6 py-20 @max-[480px]/faq:px-4 @max-[480px]/faq:py-12\";\n\nconst keyOf = (item: FaqItem) => item.id ?? item.question;\nconst normalize = (text: string) =>\n  text\n    .toLowerCase()\n    .normalize(\"NFD\")\n    .replace(/[̀-ͯ]/g, \"\");\n\n/** Wraps each match of `query` in a mark, keeping the original casing. */\nfunction Highlight({ text, query }: { text: string; query: string }) {\n  const needle = normalize(query.trim());\n  if (!needle) return <>{text}</>;\n  const haystack = normalize(text);\n  const parts: ReactNode[] = [];\n  let from = 0,\n    at = haystack.indexOf(needle);\n  while (at >= 0) {\n    if (at > from) parts.push(text.slice(from, at));\n    parts.push(\n      <mark key={at} className=\"rounded-[4px] bg-accent-tint px-px text-inherit\">\n        {text.slice(at, at + needle.length)}\n      </mark>,\n    );\n    from = at + needle.length;\n    at = haystack.indexOf(needle, from);\n  }\n  parts.push(text.slice(from));\n  return <>{parts}</>;\n}\n\n/** A short window of the answer around the first match, for closed items that match only in their answer. */\nfunction snippet(answer: string, query: string) {\n  const at = normalize(answer).indexOf(normalize(query.trim()));\n  if (at < 0) return null;\n  const start = Math.max(0, answer.lastIndexOf(\" \", Math.max(0, at - 36)) + 1);\n  const end = Math.min(answer.length, at + query.length + 60);\n  return `${start > 0 ? \"…\" : \"\"}${answer.slice(start, end).trim()}${end < answer.length ? \"…\" : \"\"}`;\n}\n\nconst panelVariants: Variants = {\n  open: {\n    height: \"auto\",\n    opacity: 1,\n    transition: { height: motionTokens.spring.smooth, opacity: { duration: duration.fast, ease: enter } },\n  },\n  closed: {\n    height: 0,\n    opacity: 0,\n    transition: { height: motionTokens.spring.smooth, opacity: { duration: duration.instant, ease: standard } },\n  },\n};\nconst contentVariants: Variants = {\n  open: {\n    y: 0,\n    filter: \"blur(0px)\",\n    transition: { y: motionTokens.spring.smooth, filter: { duration: duration.fast, ease: enter } },\n  },\n  closed: {\n    y: -6,\n    filter: `blur(${motionTokens.blur.subtle}px)`,\n    transition: { duration: duration.instant, ease: standard },\n  },\n};\nconst reducedPanel: Variants = {\n  open: { height: \"auto\", opacity: 1, transition: { duration: 0 } },\n  closed: { height: 0, opacity: 0, transition: { duration: 0 } },\n};\n/* The server cannot know the reduced-motion setting, so both content variants share the same open state: an open answer\n   hydrates with identical styles whichever branch the client takes. */\nconst reducedContent: Variants = {\n  open: { y: 0, filter: \"blur(0px)\", transition: { duration: 0 } },\n  closed: { y: 0, filter: \"blur(0px)\", transition: { duration: 0 } },\n};\n\n/** Arrow keys, Home, and End move between the questions of one list. */\nfunction onListKeyDown(event: KeyboardEvent<HTMLElement>) {\n  if (![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(event.key)) return;\n  const triggers = Array.from(event.currentTarget.querySelectorAll<HTMLElement>(\"[data-faq-trigger]\"));\n  const index = triggers.indexOf(document.activeElement as HTMLElement);\n  if (index < 0) return;\n  event.preventDefault();\n  const next =\n    event.key === \"Home\"\n      ? 0\n      : event.key === \"End\"\n        ? triggers.length - 1\n        : (index + (event.key === \"ArrowDown\" ? 1 : -1) + triggers.length) % triggers.length;\n  triggers[next]!.focus();\n}\n\nfunction Question({\n  item,\n  open,\n  onToggle,\n  query = \"\",\n  reduced,\n  baseId,\n  layout,\n}: {\n  item: FaqItem;\n  open: boolean;\n  onToggle: () => void;\n  query?: string;\n  reduced: boolean;\n  baseId: string;\n  layout?: boolean;\n}) {\n  const key = keyOf(item);\n  const safe = `${baseId}-${key.replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n  const hint =\n    query && !open && !normalize(item.question).includes(normalize(query.trim())) ? snippet(item.answer, query) : null;\n  return (\n    <motion.li\n      className=\"overflow-hidden border-b border-line\"\n      data-open={open ? \"\" : undefined}\n      layout={layout && !reduced ? \"position\" : false}\n      initial={layout ? (reduced ? { opacity: 0 } : { opacity: 0, height: 0 }) : false}\n      animate={{ opacity: 1, height: \"auto\" }}\n      exit={\n        reduced\n          ? { opacity: 0, transition: { duration: 0 } }\n          : {\n              opacity: 0,\n              height: 0,\n              transition: { height: motionTokens.spring.smooth, opacity: { duration: duration.instant } },\n            }\n      }\n      transition={\n        reduced\n          ? { duration: 0 }\n          : {\n              height: motionTokens.spring.smooth,\n              opacity: { duration: duration.fast },\n              layout: motionTokens.spring.smooth,\n            }\n      }\n    >\n      <h3 className=\"m-0\">\n        <button\n          type=\"button\"\n          id={`${safe}-q`}\n          className=\"group/trigger flex min-h-16 w-full cursor-pointer items-center justify-between gap-4 border-0 bg-transparent px-1 py-4 text-left text-base leading-body font-medium text-ink [-webkit-tap-highlight-color:transparent]\"\n          data-faq-trigger=\"\"\n          aria-expanded={open}\n          aria-controls={`${safe}-a`}\n          onClick={onToggle}\n        >\n          <span className=\"min-w-0\">\n            <Highlight text={item.question} query={query} />\n          </span>\n          <Plus\n            className={cn(\n              \"flex-none [transition:transform_var(--duration-spring)_var(--ease-spring),color_var(--duration-fast)_var(--ease-standard)] motion-reduce:transition-none\",\n              open ? \"text-ink [transform:rotate(45deg)]\" : \"text-ink-3 group-hover/trigger:text-ink\",\n            )}\n            size={18}\n            strokeWidth={1.75}\n            aria-hidden=\"true\"\n          />\n        </button>\n      </h3>\n      <AnimatePresence initial={false}>\n        {hint && (\n          <motion.p\n            key=\"hint\"\n            className=\"m-0 overflow-hidden pt-0 pr-10 pb-4 pl-1 text-sm leading-body text-ink-3 @max-[480px]/faq:pr-2\"\n            initial={{ opacity: 0, height: 0 }}\n            animate={{ opacity: 1, height: \"auto\" }}\n            exit={{ opacity: 0, height: 0 }}\n            transition={\n              reduced ? { duration: 0 } : { height: motionTokens.spring.smooth, opacity: { duration: duration.fast } }\n            }\n          >\n            <Highlight text={hint} query={query} />\n          </motion.p>\n        )}\n      </AnimatePresence>\n      <AnimatePresence initial={false}>\n        {open && (\n          <motion.section\n            key=\"answer\"\n            id={`${safe}-a`}\n            aria-labelledby={`${safe}-q`}\n            className=\"overflow-hidden\"\n            variants={reduced ? reducedPanel : panelVariants}\n            initial=\"closed\"\n            animate=\"open\"\n            exit=\"closed\"\n          >\n            <motion.p\n              className=\"m-0 pt-0 pr-10 pb-5 pl-1 text-base leading-[1.6] text-ink-2 text-pretty @max-[480px]/faq:pr-2\"\n              variants={reduced ? reducedContent : contentVariants}\n            >\n              <Highlight text={item.answer} query={query} />\n            </motion.p>\n          </motion.section>\n        )}\n      </AnimatePresence>\n    </motion.li>\n  );\n}\n\n/** The way to reach a person: a quiet card whose arrow leans forward on hover. */\nconst contactClass =\n  \"group/contact flex w-full cursor-pointer items-center justify-between gap-4 rounded-[20px] border border-line bg-surface px-5 py-4 text-left text-ink no-underline [-webkit-tap-highlight-color:transparent] [transition:transform_var(--duration-fast)_var(--ease-standard),background-color_var(--duration-fast)_var(--ease-standard)] hover:bg-hover active:[transform:scale(.99)] motion-reduce:transition-none motion-reduce:active:[transform:none]\";\n\nfunction Contact({ contact }: { contact: NonNullable<FaqSectionProps[\"contact\"]> }) {\n  const inner = (\n    <>\n      <span className=\"grid min-w-0 gap-0.5\">\n        <span className=\"text-sm/[inherit] font-medium\">{contact.label}</span>\n        {contact.description && <span className=\"text-sm/[inherit] text-ink-3\">{contact.description}</span>}\n      </span>\n      <ArrowRight\n        className=\"flex-none text-ink-3 transition-transform duration-fast ease-standard group-hover/contact:translate-x-0.5 group-hover/contact:text-ink motion-reduce:transition-none\"\n        size={16}\n        strokeWidth={1.75}\n        aria-hidden=\"true\"\n      />\n    </>\n  );\n  return contact.href ? (\n    <a className={contactClass} href={contact.href} onClick={contact.onClick}>\n      {inner}\n    </a>\n  ) : (\n    <button type=\"button\" className={contactClass} onClick={contact.onClick}>\n      {inner}\n    </button>\n  );\n}\n\n/**\n * A frequently asked questions section in three layouts: one centered accordion, a category rail beside its questions,\n * and a searchable list that filters and highlights as you type. Answers open on a height spring with the icon turning\n * to a close mark; arrow keys move between questions.\n */\nexport const FaqSection = forwardRef<HTMLElement, FaqSectionProps>(function FaqSection(\n  {\n    variant = \"accordion\",\n    title = \"Frequently asked questions\",\n    description = \"What marketing teams ask before they connect their first brand.\",\n    items = faqExampleItems,\n    multiple = false,\n    value,\n    defaultValue,\n    onValueChange,\n    category: categoryProp,\n    onCategoryChange,\n    query: queryProp,\n    onQueryChange,\n    contact = { label: \"Still have a question?\", description: \"Our team replies within a day.\" },\n    className,\n  },\n  ref,\n) {\n  const id = useId();\n  const reduced = !!useReducedMotion();\n  const [innerOpen, setInnerOpen] = useState<string[]>(defaultValue ?? (items[0] ? [keyOf(items[0])] : []));\n  const open = value ?? innerOpen;\n  const categories = useMemo(() => Array.from(new Set(items.map((item) => item.category ?? \"General\"))), [items]);\n  const [innerCategory, setInnerCategory] = useState(categories[0] ?? \"General\");\n  const activeCategory = categoryProp ?? innerCategory;\n  const [direction, setDirection] = useState(0);\n  const [innerQuery, setInnerQuery] = useState(\"\");\n  const query = queryProp ?? innerQuery;\n\n  const setOpen = (next: string[]) => {\n    if (value === undefined) setInnerOpen(next);\n    onValueChange?.(next);\n  };\n  const toggle = (key: string) =>\n    setOpen(open.includes(key) ? open.filter((entry) => entry !== key) : multiple ? [...open, key] : [key]);\n  const chooseCategory = (next: string) => {\n    if (next === activeCategory) return;\n    setDirection(Math.sign(categories.indexOf(next) - categories.indexOf(activeCategory)));\n    if (categoryProp === undefined) setInnerCategory(next);\n    onCategoryChange?.(next);\n  };\n  const setQuery = (next: string) => {\n    if (queryProp === undefined) setInnerQuery(next);\n    onQueryChange?.(next);\n  };\n\n  const needle = normalize(query.trim());\n  const results =\n    variant === \"search\" && needle\n      ? items.filter((item) => normalize(`${item.question} ${item.answer}`).includes(needle))\n      : items;\n  const heading = (\n    <div className={cn(\"grid gap-3\", variant !== \"columns\" && \"justify-items-center text-center\")}>\n      <h2\n        id={`${id}-title`}\n        className=\"m-0 font-display text-3xl leading-display font-medium tracking-display text-balance @min-[720px]/faq:text-4xl\"\n      >\n        {title}\n      </h2>\n      {description && <p className=\"m-0 max-w-[480px] text-base leading-body text-pretty text-ink-2\">{description}</p>}\n    </div>\n  );\n  // Arrow keys are handled once on the list and move focus between its question buttons.\n  const list = (entries: FaqItem[], layout = false) => (\n    // oxlint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- delegated from the question buttons inside\n    <ul className=\"m-0 list-none border-t border-line p-0\" onKeyDown={onListKeyDown}>\n      <AnimatePresence initial={false}>\n        {entries.map((item) => (\n          <Question\n            key={keyOf(item)}\n            item={item}\n            open={open.includes(keyOf(item))}\n            onToggle={() => toggle(keyOf(item))}\n            query={variant === \"search\" ? query : \"\"}\n            reduced={reduced}\n            baseId={id}\n            layout={layout}\n          />\n        ))}\n      </AnimatePresence>\n    </ul>\n  );\n\n  return (\n    <section\n      ref={ref}\n      className={cn(\"@container/faq bg-page font-body tracking-body text-ink\", className)}\n      data-variant={variant}\n      aria-labelledby={`${id}-title`}\n    >\n      {variant === \"accordion\" && (\n        <div className={stack}>\n          {heading}\n          {list(items)}\n          {contact && <Contact contact={contact} />}\n        </div>\n      )}\n\n      {variant === \"columns\" && (\n        <div className=\"mx-auto grid max-w-[1120px] grid-cols-[minmax(0,.8fr)_minmax(0,1.2fr)] items-start gap-16 px-8 py-20 @max-[760px]/faq:grid-cols-[minmax(0,1fr)] @max-[760px]/faq:gap-8 @max-[760px]/faq:px-6 @max-[480px]/faq:px-4 @max-[480px]/faq:py-12\">\n          <div className=\"sticky top-6 grid gap-6 @max-[760px]/faq:static\">\n            {heading}\n            <LayoutGroup id={`${id}-rail`}>\n              <div\n                className=\"grid gap-0.5 @max-[760px]/faq:flex @max-[760px]/faq:overflow-x-auto @max-[760px]/faq:[scrollbar-width:none] @max-[760px]/faq:[&::-webkit-scrollbar]:hidden\"\n                role=\"group\"\n                aria-label=\"Question topics\"\n              >\n                {categories.map((entry) => {\n                  const count = items.filter((item) => (item.category ?? \"General\") === entry).length;\n                  return (\n                    <button\n                      key={entry}\n                      type=\"button\"\n                      className={cn(\n                        \"relative isolate flex h-10 cursor-pointer items-center justify-between gap-3 rounded-button border-0 bg-transparent px-3.5 text-left text-sm/[inherit] font-medium whitespace-nowrap [-webkit-tap-highlight-color:transparent] transition-[color] duration-fast ease-standard hover:text-ink motion-reduce:transition-none @max-[760px]/faq:flex-none\",\n                        entry === activeCategory ? \"text-ink\" : \"text-ink-2\",\n                      )}\n                      aria-pressed={entry === activeCategory}\n                      onClick={() => chooseCategory(entry)}\n                    >\n                      {entry === activeCategory && (\n                        <motion.span\n                          layoutId=\"category\"\n                          className=\"absolute inset-0 -z-10 rounded-[inherit] bg-hover\"\n                          transition={reduced ? { duration: 0 } : motionTokens.spring.morph}\n                          aria-hidden=\"true\"\n                        />\n                      )}\n                      <span>{entry}</span>\n                      <span className=\"text-xs/[inherit] text-ink-3 tabular-nums\">{count}</span>\n                    </button>\n                  );\n                })}\n              </div>\n            </LayoutGroup>\n            {contact && <Contact contact={contact} />}\n          </div>\n          <div className=\"relative min-w-0\">\n            <AnimatePresence initial={false} mode=\"popLayout\" custom={direction}>\n              <motion.div\n                key={activeCategory}\n                className=\"w-full\"\n                custom={direction}\n                initial={\n                  reduced\n                    ? { opacity: 0 }\n                    : { opacity: 0, y: direction * 16, filter: `blur(${motionTokens.blur.subtle}px)` }\n                }\n                animate={{ opacity: 1, y: 0, filter: \"blur(0px)\" }}\n                exit={\n                  reduced\n                    ? { opacity: 0, transition: { duration: 0 } }\n                    : {\n                        opacity: 0,\n                        y: direction * -12,\n                        filter: `blur(${motionTokens.blur.subtle}px)`,\n                        transition: { duration: duration.instant, ease: standard },\n                      }\n                }\n                transition={\n                  reduced\n                    ? { duration: 0 }\n                    : {\n                        y: motionTokens.spring.smooth,\n                        opacity: { duration: duration.fast, ease: enter },\n                        filter: { duration: duration.fast, ease: enter },\n                      }\n                }\n              >\n                {list(items.filter((item) => (item.category ?? \"General\") === activeCategory))}\n              </motion.div>\n            </AnimatePresence>\n          </div>\n        </div>\n      )}\n\n      {variant === \"search\" && (\n        <div className={stack}>\n          {heading}\n          <div className=\"grid gap-2\">\n            <SearchField\n              label=\"Search questions\"\n              placeholder=\"Try voice, publish, or plan\"\n              value={query}\n              onValueChange={setQuery}\n            />\n            <p className=\"m-0 text-sm/[inherit] text-ink-3 tabular-nums\" aria-live=\"polite\">\n              {needle\n                ? `${results.length} ${results.length === 1 ? \"answer\" : \"answers\"}`\n                : `${items.length} questions`}\n            </p>\n          </div>\n          {list(results, true)}\n          <AnimatePresence initial={false}>\n            {needle && results.length === 0 && (\n              <motion.div\n                key=\"empty\"\n                className=\"grid justify-items-center gap-3 py-6 text-center\"\n                initial={reduced ? { opacity: 0 } : { opacity: 0, y: 8 }}\n                animate={{ opacity: 1, y: 0 }}\n                exit={{ opacity: 0, transition: { duration: duration.instant } }}\n                transition={{ duration: reduced ? 0 : duration.standard, ease: enter }}\n              >\n                <p className=\"m-0 text-sm/[inherit] text-ink-2\">No answers mention “{query.trim()}”.</p>\n                <button\n                  type=\"button\"\n                  className=\"h-control-sm cursor-pointer rounded-button border border-line bg-surface px-4 text-sm/[inherit] font-medium text-ink transition-transform duration-fast ease-standard active:[transform:scale(.97)] motion-reduce:transition-none motion-reduce:active:[transform:none]\"\n                  onClick={() => setQuery(\"\")}\n                >\n                  Clear search\n                </button>\n              </motion.div>\n            )}\n          </AnimatePresence>\n          {contact && <Contact contact={contact} />}\n        </div>\n      )}\n    </section>\n  );\n});\n\nFaqSection.displayName = \"FaqSection\";\n\nconst variantOptions = [\n  { value: \"accordion\", label: \"Accordion\" },\n  { value: \"columns\", label: \"Two column\" },\n  { value: \"search\", label: \"Searchable\" },\n];\n\n/** Preview: the FAQ with a switch between its three layouts. */\nexport function FaqSectionBlock({ variant: initial = \"accordion\" }: { variant?: FaqSectionVariant }) {\n  const [variant, setVariant] = useState<FaqSectionVariant>(initial);\n  const [asked, setAsked] = useState(false);\n  return (\n    <div className=\"grid w-full justify-items-center gap-4\">\n      <SegmentedControl\n        label=\"FAQ layout\"\n        options={variantOptions}\n        value={variant}\n        onValueChange={(next) => setVariant(next as FaqSectionVariant)}\n      />\n      <div className=\"w-full overflow-hidden rounded-[20px] border border-line bg-page\">\n        <FaqSection\n          key={variant}\n          variant={variant}\n          contact={{\n            label: asked ? \"Message sent to support\" : \"Still have a question?\",\n            description: asked ? \"Katerina will reply within a day.\" : \"Our team replies within a day.\",\n            onClick: () => setAsked(true),\n          }}\n        />\n      </div>\n    </div>\n  );\n}\n\nexport default FaqSectionBlock;\n",
      "type": "registry:component",
      "target": "@components/iris/blocks/faq-section/faq-section.tsx"
    }
  ],
  "docs": "Docs and live preview: https://irisui.dev/components/faq-section",
  "meta": {
    "kind": "block",
    "group": "Blocks",
    "export": "FaqSection",
    "docs": "https://irisui.dev/components/faq-section"
  }
}
