{
  "generatedFrom": "collapse.contract.json",
  "component": "Collapse",
  "slug": "collapse",
  "group": "Data Display",
  "tier": "leaf-lit",
  "summary": "A single expandable panel that hides secondary content until asked.",
  "install": {
    "package": "@ahaslides-product/design",
    "registry": "https://npm.pkg.github.com",
    "scope": "@ahaslides-product",
    "auth": "Published to GitHub Packages — needs a GitHub token with read:packages. Configure the @ahaslides-product scope in .npmrc before installing.",
    "npmrc": "@ahaslides-product:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}   # a GitHub token with read:packages",
    "command": "npm i @ahaslides-product/design",
    "tokenLayer": "import '@ahaslides-product/design/tokens.css';",
    "import": "import '@ahaslides-product/design/aha-collapse';",
    "element": "aha-collapse",
    "registers": "aha-collapse"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/collapse/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/collapse/collapse.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/collapse.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/collapse.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-collapse> is a standard custom element that renders on open — React/Vue are thin adapters over the same element. Paste into an .html file and it renders with no build step.",
  "frameworks": {
    "react": {
      "via": "web-component",
      "ref": "aha-collapse"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-collapse"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-collapse",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "open",
      "type": "boolean",
      "default": "false",
      "desc": "Whether the panel is expanded; toggled on header click (observed → aria-expanded synced)"
    },
    {
      "name": "accordion",
      "type": "boolean",
      "default": "false",
      "desc": "Opening this panel closes sibling accordion panels under the same parent (one-open-at-a-time)"
    },
    {
      "name": "ghost",
      "type": "boolean",
      "default": "false",
      "desc": "Borderless, transparent surface that sits seamlessly on the page"
    },
    {
      "name": "size",
      "type": "'small'",
      "default": "—",
      "desc": "Denser header + body padding"
    },
    {
      "name": "icon-position",
      "type": "'start' | 'end'",
      "default": "start",
      "desc": "Caret on the leading or trailing edge of the header"
    },
    {
      "name": "disabled",
      "type": "boolean",
      "default": "false",
      "desc": "Non-interactive, dimmed panel (observed → aria-disabled synced)"
    },
    {
      "name": "header",
      "type": "slot",
      "default": "Section",
      "desc": "The always-visible summary row"
    },
    {
      "name": "extra",
      "type": "slot",
      "default": "—",
      "desc": "A trailing header accessory (a tag, a count, an icon)"
    },
    {
      "name": "toggle",
      "type": "CustomEvent<{open}>",
      "default": "—",
      "desc": "Composed event; read e.detail.open"
    }
  ],
  "tokens": [
    "bg-container",
    "border",
    "split",
    "radius-default",
    "text-default",
    "text-secondary",
    "text-disabled",
    "bg-hover",
    "icon-default",
    "border-focus",
    "font-product"
  ],
  "spec": [
    {
      "label": "Panel",
      "value": "border 1px #E3E3E3 · radius 8px · bg #FFFFFF (ghost: borderless, transparent)"
    },
    {
      "label": "Header",
      "value": "padding 14/16 · 15/22 SemiBold #1A1A1A · hover #F7F7F7 (small: 8/12 · 14/20)"
    },
    {
      "label": "Caret",
      "value": "system-caret-right <aha-icon>, rotate 0°→90° on open, motion-mid ease-in-out"
    },
    {
      "label": "Icon position",
      "value": "start (leading, default) or end (trailing edge, via order)"
    },
    {
      "label": "Body",
      "value": "grid-rows 0fr→1fr, motion-mid ease-in-out · 14/22 #4A4A4A"
    },
    {
      "label": "Disabled",
      "value": "text-disabled #B5B5B5, not-allowed, hover suppressed, aria-disabled"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Collapse",
        "when": "hiding secondary detail (advanced settings, an FAQ answer) until wanted"
      },
      {
        "what": "Tabs",
        "when": "switching between peer views of equal importance"
      },
      {
        "what": "Card",
        "when": "content that should always be visible"
      }
    ],
    "note": "Header text names what's inside — 'Advanced settings', not 'More'. Keep panels shallow; deep nesting hides content people never find.",
    "dsv3": "COVERED — enumerated from the DS V3 Collapse component-set taxonomy (fileKey MwjvUjVI0HnfwD9EwPXRAy): a Collapse container + a Collapse-Item, mirroring antd — the container carries accordion / bordered vs ghost / size / expand-icon position, the item carries disabled + an extra accessory. DS V3's measured cell set has no Collapse px/rgb, so the look is derived from the token layer (radius-default, border, split, bg-hover, icon-default, text-disabled) + antd Collapse conventions. A deliberate, documented extension — not a measured match."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     <aha-collapse> is the SAME shared custom element React and Vue consume — here in its\n     native form. Theming comes only from the --aha-* tokens in tokens.css.\n     accordion → one panel open at a time · disabled → read-only · slot=\"extra\" → header accessory\n     ghost → borderless · size=\"small\" → dense · icon-position=\"end\" → caret trailing. -->\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/tokens.css\">\n<script type=\"module\">\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/icons.js';        // registers <aha-icon>\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-collapse.js'; // registers <aha-collapse>\n</script>\n\n<div style=\"display:flex; flex-direction:column; gap:8px; max-width:380px\">\n  <aha-collapse accordion open>\n    <span slot=\"header\">Advanced settings</span>\n    <aha-icon slot=\"extra\" name=\"system-star\" size=\"14\" aria-hidden=\"true\"></aha-icon>\n    Let participants join anonymously, and shuffle the answer order.\n  </aha-collapse>\n  <aha-collapse accordion id=\"scoring\">\n    <span slot=\"header\">Scoring</span>\n    Award points by speed, and show a leaderboard between rounds.\n  </aha-collapse>\n  <aha-collapse disabled>\n    <span slot=\"header\">Billing (read-only)</span>\n    Managed by your workspace owner.\n  </aha-collapse>\n</div>\n\n<script>\n  document.getElementById('scoring').addEventListener('toggle', (e) => console.log('open:', e.detail.open));\n</script>\n",
    "react": "import '@ahaslides-product/design/aha-collapse';   // registers <aha-collapse>\nimport '@ahaslides-product/design/icons';          // registers <aha-icon>\nimport { useRef, useEffect } from 'react';\n\n// React 18 needs a thin wrapper for the composed `toggle` event; React 19 can bind onToggle directly.\nfunction AhaCollapse({ header, extra, open, disabled, accordion, size, ghost, iconPosition, onToggle, children }) {\n  const ref = useRef();\n  useEffect(() => {\n    const el = ref.current;\n    const h = (e) => onToggle?.(e.detail.open);\n    el.addEventListener('toggle', h);\n    return () => el.removeEventListener('toggle', h);\n  });\n  return (\n    <aha-collapse\n      ref={ref}\n      {...(open ? { open: '' } : {})}\n      {...(disabled ? { disabled: '' } : {})}\n      {...(accordion ? { accordion: '' } : {})}\n      {...(ghost ? { ghost: '' } : {})}\n      {...(size ? { size } : {})}\n      {...(iconPosition ? { 'icon-position': iconPosition } : {})}\n    >\n      <span slot=\"header\">{header}</span>\n      {extra && <span slot=\"extra\">{extra}</span>}\n      {children}\n    </aha-collapse>\n  );\n}\n\n// usage — accordion group: opening one closes its siblings\n<AhaCollapse header=\"Advanced settings\" accordion open onToggle={(o) => setOpen(o)}>\n  Let participants join anonymously, and shuffle the answer order.\n</AhaCollapse>\n<AhaCollapse header=\"Scoring\" accordion>Award points by speed.</AhaCollapse>\n<AhaCollapse header=\"Billing (read-only)\" disabled>Managed by your workspace owner.</AhaCollapse>\n",
    "vue": "// main.ts — register the elements + mark aha-* as custom elements\nimport '@ahaslides-product/design/aha-collapse';\nimport '@ahaslides-product/design/icons';\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue\n<script setup>\nimport { ref } from 'vue';\nconst open = ref(true);\n</script>\n\n<template>\n  <!-- accordion group: opening one panel closes its siblings -->\n  <aha-collapse\n    accordion\n    :open=\"open || undefined\"\n    @toggle=\"open = $event.detail.open\"\n  >\n    <span slot=\"header\">Advanced settings</span>\n    <aha-icon slot=\"extra\" name=\"system-star\" size=\"14\" aria-hidden=\"true\" />\n    Let participants join anonymously, and shuffle the answer order.\n  </aha-collapse>\n  <aha-collapse accordion>\n    <span slot=\"header\">Scoring</span>\n    Award points by speed, and show a leaderboard between rounds.\n  </aha-collapse>\n  <aha-collapse disabled>\n    <span slot=\"header\">Billing (read-only)</span>\n    Managed by your workspace owner.\n  </aha-collapse>\n</template>\n"
  }
}
