{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "collapsible",
  "type": "registry:ui",
  "title": "Collapsible",
  "description": "@interlace/ui — collapsible primitive (shadcn-compatible).",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "theme"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/collapsible.tsx",
      "target": "components/ui/collapsible.tsx",
      "type": "registry:ui",
      "content": "'use client';\n\n/**\n * @interlace/ui — Collapsible\n *\n * A single open/close disclosure surface. Wraps Base UI's `Collapsible.Root`,\n * `Collapsible.Trigger`, `Collapsible.Panel` so consumers get the controlled /\n * uncontrolled state machine, ARIA wiring (`aria-controls`, `aria-expanded`,\n * `id`), keyboard semantics (Enter / Space on the trigger), and Base UI's\n * built-in panel sizing — for free. Reduced-motion is honoured globally via\n * `preflight.css` (every animation collapses to 0.01ms when\n * `prefers-reduced-motion: reduce`), so this file owns no motion timing.\n *\n * ## Anatomy\n *\n *   Collapsible (Base.Root, data-min-viewport)\n *     ├─ CollapsibleTrigger (Base.Trigger — button surface)\n *     └─ CollapsiblePanel   (Base.Panel — height-animated container)\n *\n * ## MIN_VIEWPORT — 320\n *\n * A disclosure is one of the smallest interactive surfaces a page can offer:\n * a single trigger + a single content region. It works down to the 320 CSS-px\n * iPhone SE viewport — the trigger inherits focus-visible / target-size\n * affordances from `preflight.css`, and the panel is width-constrained by its\n * parent, never the viewport. Below 320, preflight's dev-mode outline warns.\n *\n * | Rule | Concept                          | Where in this file                                                  |\n * | ---- | -------------------------------- | ------------------------------------------------------------------- |\n * | R4   | Extends Base UI part props       | Each part: `React.ComponentProps<typeof BaseCollapsible.X>`         |\n * | R6   | data-slot on every part          | data-slot=\"collapsible\" / \"collapsible-trigger\" / \"collapsible-panel\" |\n * | R7   | className merged + ...rest       | `cn(BASE, className)` + `{...props}` on every part                  |\n * | R10  | Composition seam                 | Base UI parts are renderable / slot-friendly out of the box         |\n * | R13  | Ecosystem first                  | Base UI Collapsible — no bespoke disclosure state machine           |\n * | R14  | Declares min viewport            | `data-min-viewport={String(MIN_VIEWPORT)}` + exported const         |\n * | R18  | Tailwind only                    | Zero inline `style`; classes only                                   |\n * | R19  | Tokens only                      | `text-ui font-medium` from foundation tokens (no raw px / colors)   |\n * | R20  | AA contrast                      | Trigger inherits foreground; focus ring from preflight              |\n * | R25  | Client component                 | Base UI Collapsible is a client surface → `'use client'` required   |\n * | R26  | A11y from Base UI                | aria-expanded / aria-controls / Enter+Space owned by Base UI        |\n *\n * API parity: Radix / shadcn `Collapsible` (Root + Trigger + Content) — we\n * keep the same three-part shape, renaming `Content` → `Panel` to match Base\n * UI's vocabulary. Consumers wanting Radix-style naming can re-alias on import.\n */\n\nimport * as React from 'react';\nimport { Collapsible as BaseCollapsible } from '@base-ui/react/collapsible';\n\nimport { cn } from '@/lib/utils';\n\n/**\n * Minimum viable viewport (CSS px) for this primitive. Below it, the\n * preflight contract draws a dev-mode outline; in prod the component still\n * renders. Exported so consumers / tests can read it.\n */\nexport const MIN_VIEWPORT = 320 as const;\n\n// ─────────────────────────────────────────────────────────────────\n// Collapsible (Base.Root) — owns the open/closed state machine.\n// ─────────────────────────────────────────────────────────────────\nconst Collapsible = React.forwardRef<\n  React.ElementRef<typeof BaseCollapsible.Root>,\n  React.ComponentProps<typeof BaseCollapsible.Root>\n>(function Collapsible({ className, ...props }, ref) {\n  return (\n    <BaseCollapsible.Root\n      ref={ref}\n      data-slot=\"collapsible\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      className={cn(className)}\n      {...props}\n    />\n  );\n});\nCollapsible.displayName = 'Collapsible';\n\n// ─────────────────────────────────────────────────────────────────\n// CollapsibleTrigger (Base.Trigger) — the button surface.\n// Inherits focus-visible ring + target-size floor from preflight.css.\n// ─────────────────────────────────────────────────────────────────\nconst CollapsibleTrigger = React.forwardRef<\n  React.ElementRef<typeof BaseCollapsible.Trigger>,\n  React.ComponentProps<typeof BaseCollapsible.Trigger>\n>(function CollapsibleTrigger({ className, ...props }, ref) {\n  return (\n    <BaseCollapsible.Trigger\n      ref={ref}\n      data-slot=\"collapsible-trigger\"\n      className={cn(\n        'text-ui font-medium outline-none disabled:pointer-events-none disabled:opacity-50',\n        className,\n      )}\n      {...props}\n    />\n  );\n});\nCollapsibleTrigger.displayName = 'CollapsibleTrigger';\n\n// ─────────────────────────────────────────────────────────────────\n// CollapsiblePanel (Base.Panel) — height-animated content region.\n// Base UI sets the `height` CSS var across open/closed; we only need to\n// clip overflow so the animation reads cleanly. `data-[starting-style]` /\n// `data-[ending-style]` collapse height to 0 at the boundary; reduced-motion\n// short-circuits the animation duration to 0.01ms via preflight.\n// ─────────────────────────────────────────────────────────────────\nconst CollapsiblePanel = React.forwardRef<\n  React.ElementRef<typeof BaseCollapsible.Panel>,\n  React.ComponentProps<typeof BaseCollapsible.Panel>\n>(function CollapsiblePanel({ className, ...props }, ref) {\n  return (\n    <BaseCollapsible.Panel\n      ref={ref}\n      data-slot=\"collapsible-panel\"\n      className={cn(\n        'overflow-hidden transition-[height] data-[ending-style]:h-0 data-[starting-style]:h-0',\n        className,\n      )}\n      {...props}\n    />\n  );\n});\nCollapsiblePanel.displayName = 'CollapsiblePanel';\n\nexport { Collapsible, CollapsibleTrigger, CollapsiblePanel };\n"
    }
  ]
}
