{
  "generatedFrom": "card.contract.json",
  "component": "Card",
  "slug": "card",
  "group": "Data Display",
  "tier": "leaf-lit",
  "summary": "A surface that groups related content — cover, title, body and footer actions — in default/small size, bordered or flat, with a hover lift and a loading skeleton.",
  "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-card';",
    "element": "aha-card",
    "registers": "aha-card"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/card/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/card/card.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/card.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/card.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-card> 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-card"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-card"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-card",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "card-title",
      "type": "string",
      "default": "—",
      "desc": "Renders the header row; omit for a bare body"
    },
    {
      "name": "size",
      "type": "'default' | 'small'",
      "default": "default",
      "desc": "Padding density of header/body/actions"
    },
    {
      "name": "bordered",
      "type": "boolean-ish",
      "default": "true",
      "desc": "Set bordered=\"false\" for a flat, outline-less surface"
    },
    {
      "name": "hoverable",
      "type": "boolean",
      "default": "false",
      "desc": "Lift the card (border + shadow) on hover"
    },
    {
      "name": "loading",
      "type": "boolean",
      "default": "false",
      "desc": "Swap the body for a shimmer skeleton while content loads"
    },
    {
      "name": "cover",
      "type": "slot",
      "default": "—",
      "desc": "Full-bleed image/media above the header"
    },
    {
      "name": "extra",
      "type": "slot",
      "default": "—",
      "desc": "Right-aligned header action (a link or button)"
    },
    {
      "name": "actions",
      "type": "slot",
      "default": "—",
      "desc": "Ruled-off footer row of actions"
    }
  ],
  "tokens": [
    "bg-container",
    "border",
    "border-hover",
    "split",
    "radius-lg",
    "radius-sm",
    "text-default",
    "text-secondary",
    "ink-a10",
    "bg-hover",
    "font-product",
    "motion-mid",
    "motion-slow",
    "ease-out"
  ],
  "spec": [
    {
      "label": "Container",
      "value": "border 1px #E3E3E3 · radius 12px · bg #FFFFFF"
    },
    {
      "label": "Cover",
      "value": "full-bleed media above the header, no inset; hidden when the slot is empty"
    },
    {
      "label": "Header",
      "value": "padding 16/20 · 16/24 SemiBold #1A1A1A · divider #F1F1F1 · extra action right-aligned"
    },
    {
      "label": "Body",
      "value": "padding 20 · 14/22 #4A4A4A"
    },
    {
      "label": "Actions",
      "value": "footer row, 12/20 padding, 8 gap, top divider #F1F1F1; hidden when empty"
    },
    {
      "label": "Small size",
      "value": "header 8/12 · body 12 · actions 8/12 (antd Card size=small)"
    },
    {
      "label": "Bordered=false",
      "value": "border-color transparent — a flat surface"
    },
    {
      "label": "Hover (hoverable)",
      "value": "border #D3B4FF + shadow, motion-mid ease-out on a persistent node"
    },
    {
      "label": "Loading",
      "value": "body → shimmer skeleton bars (aria-busy), motion-slow sweep"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Card",
        "when": "grouping related content into a titled surface on a dashboard or settings page"
      },
      {
        "what": "List",
        "when": "many uniform rows of the same shape"
      },
      {
        "what": "Descriptions",
        "when": "read-only label/value pairs about one entity"
      }
    ],
    "note": "Titles are sentence case and name the group — 'Live results', not 'LIVE RESULTS'. Keep one idea per card; reach for hoverable only when the whole card is clickable. Use a cover for a media-led card, footer actions for card-level operations, and loading while the body fetches.",
    "dsv3": "COVERED — enumerated from the DS V3 Card component-set taxonomy (Card + Card_Image_Wrapper for the cover, Card_Meta_Wrapper for the title/body meta, plus size/bordered/hoverable states matching antd Card). DS V3's measured set has no Card cell, so px/rgb are derived from the token layer (radius-lg, border, border-hover, split, bg-container, text-default/secondary, ink-a10) + antd Card conventions (16/24 header + 20 body default; 8/12 header + 12 body small). 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-card> 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<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-card.js'; // registers <aha-card>\n</script>\n\n<div style=\"display:flex; gap:16px; flex-wrap:wrap; align-items:flex-start\">\n  <!-- Full card: cover · title + extra action · body · footer actions · hoverable -->\n  <aha-card card-title=\"Live poll\" hoverable style=\"width:300px\">\n    <img slot=\"cover\" src=\"cover.jpg\" alt=\"\" />\n    <a slot=\"extra\" href=\"#\">Edit</a>\n    Which release cadence works best for your team?\n    <div slot=\"actions\">\n      <aha-icon name=\"system-share-network\" size=\"16\"></aha-icon>\n      <aha-icon name=\"system-bookmark-simple\" size=\"16\"></aha-icon>\n    </div>\n  </aha-card>\n\n  <!-- Small size -->\n  <aha-card size=\"small\" card-title=\"Weekly digest\" style=\"width:240px\">\n    A small card tightens its padding.\n  </aha-card>\n\n  <!-- Borderless + loading skeleton -->\n  <aha-card bordered=\"false\" card-title=\"Borderless\">No outline.</aha-card>\n  <aha-card card-title=\"Loading\" loading style=\"width:240px\"></aha-card>\n</div>\n",
    "react": "import '@ahaslides-product/design/aha-card';   // registers <aha-card>\nimport '@ahaslides-product/design/icons';      // registers <aha-icon>\n\n// The custom element renders its own shadow DOM; React just passes attributes + slots.\n// Boolean attrs (hoverable/loading) render as presence; string attrs (size/bordered) pass through.\nfunction DeckCard({ title, size, bordered, hoverable, loading, cover, extra, actions, children }) {\n  return (\n    <aha-card\n      card-title={title}\n      size={size}\n      bordered={bordered}\n      {...(hoverable ? { hoverable: '' } : {})}\n      {...(loading ? { loading: '' } : {})}\n    >\n      {cover && <img slot=\"cover\" src={cover} alt=\"\" />}\n      {extra && <a slot=\"extra\" href=\"#\">{extra}</a>}\n      {children}\n      {actions && <div slot=\"actions\">{actions}</div>}\n    </aha-card>\n  );\n}\n\n// usage\n<DeckCard title=\"Live poll\" hoverable cover=\"cover.jpg\" extra=\"Edit\"\n  actions={<><aha-icon name=\"system-share-network\" size=\"16\" /><aha-icon name=\"system-bookmark-simple\" size=\"16\" /></>}>\n  Which release cadence works best for your team?\n</DeckCard>\n<DeckCard title=\"Weekly digest\" size=\"small\">A small card tightens its padding.</DeckCard>\n<DeckCard title=\"Loading\" loading />\n",
    "vue": "// main.ts — register the elements + mark aha-* as custom elements\nimport '@ahaslides-product/design/aha-card';\nimport '@ahaslides-product/design/icons';\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue — cover · title + extra action · body · footer actions\n<template>\n  <aha-card card-title=\"Live poll\" hoverable style=\"width:300px\">\n    <img slot=\"cover\" src=\"cover.jpg\" alt=\"\" />\n    <a slot=\"extra\" href=\"#\">Edit</a>\n    Which release cadence works best for your team?\n    <div slot=\"actions\">\n      <aha-icon name=\"system-share-network\" size=\"16\" />\n      <aha-icon name=\"system-bookmark-simple\" size=\"16\" />\n    </div>\n  </aha-card>\n\n  <aha-card card-title=\"Weekly digest\" size=\"small\">A small card tightens its padding.</aha-card>\n  <aha-card card-title=\"Borderless\" bordered=\"false\">No outline.</aha-card>\n  <aha-card card-title=\"Loading\" loading />\n</template>\n"
  }
}
