{
  "generatedFrom": "list.contract.json",
  "component": "List",
  "slug": "list",
  "group": "Data Display",
  "tier": "leaf-lit",
  "summary": "A vertical list of uniform rows — avatar + title/description meta and trailing actions, with size, bordered and split options.",
  "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-list';",
    "element": "aha-list",
    "registers": "aha-list"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/list/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/list/list.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/list.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/list.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-list> 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-list"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-list"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-list",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "items",
      "type": "JSON array",
      "default": "[]",
      "desc": "Structured rows: { title, description?, avatar? (icon name), actions?:[{ key, icon, danger?, label? }] }"
    },
    {
      "name": "(children)",
      "type": "slot",
      "default": "—",
      "desc": "Free-form fallback — each light-DOM child renders as one plain row (used when `items` is empty)"
    },
    {
      "name": "size",
      "type": "'small' | 'default' | 'large'",
      "default": "default",
      "desc": "Row vertical padding scale (8 · 12 · 16)"
    },
    {
      "name": "bordered",
      "type": "boolean",
      "default": "false",
      "desc": "Draw the outer container border"
    },
    {
      "name": "split",
      "type": "boolean",
      "default": "true",
      "desc": "Row dividers; set split=\"false\" to remove them"
    },
    {
      "name": "list-title",
      "type": "string",
      "default": "—",
      "desc": "Renders an optional header row"
    },
    {
      "name": "footer",
      "type": "string",
      "default": "—",
      "desc": "Renders an optional footer row"
    },
    {
      "name": "loading",
      "type": "boolean",
      "default": "false",
      "desc": "Show shimmer skeleton rows in place of content"
    },
    {
      "name": "action",
      "type": "CustomEvent",
      "default": "—",
      "desc": "Composed event on a trailing action click, detail { key, index }"
    }
  ],
  "tokens": [
    "bg-container",
    "border",
    "split",
    "radius-lg",
    "radius-sm",
    "radius-xs",
    "radius-pill",
    "text-default",
    "text-secondary",
    "text-tertiary",
    "bg-hover",
    "bg-accent",
    "color-primary",
    "color-error",
    "border-focus",
    "font-product"
  ],
  "spec": [
    {
      "label": "Container",
      "value": "radius 12px · bg #FFFFFF · border 1px #E3E3E3 only when `bordered`"
    },
    {
      "label": "Header",
      "value": "padding 14/20 · 15/22 SemiBold #1A1A1A · divider #F1F1F1"
    },
    {
      "label": "Row",
      "value": "padding 12/20 (small 8, large 16) · 14/22 #4A4A4A · avatar 36 + meta + trailing actions"
    },
    {
      "label": "Avatar",
      "value": "36px pill, bg-accent #F9F5FF fill, color-primary #6A1EBB glyph"
    },
    {
      "label": "Meta",
      "value": "title 600 #1A1A1A + description 13/20 #8A8A8A, both ellipsised"
    },
    {
      "label": "Action",
      "value": "28px icon button, text-tertiary #8A8A8A; danger hover error-tinted"
    },
    {
      "label": "Split",
      "value": "row dividers #F1F1F1, on by default; split=false drops them"
    },
    {
      "label": "Row hover",
      "value": "interactive rows → bg #F7F7F7, motion-fast ease-out (persistent node)"
    },
    {
      "label": "Footer",
      "value": "padding 12/20 · 13/20 #8A8A8A · top divider"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "List",
        "when": "many uniform rows of the same shape (recent items, participants, feeds)"
      },
      {
        "what": "Table",
        "when": "multi-column records that need sorting or alignment"
      },
      {
        "what": "Card",
        "when": "one titled group of mixed content"
      }
    ],
    "note": "Keep rows to one shape — a title, optionally a description and a small trailing actions cluster. Reserve `bordered` for a standalone list; drop the border when the list sits inside a card. For dense multi-column data reach for the Table instead.",
    "dsv3": "COVERED — DS V3's measured set has no dedicated data-List container cell (search returns only list icons + the distinct Upload List Item primitive); the matrix follows antd List conventions over the DS token layer: size (small/default/large row padding), bordered (outer border), split (row dividers), optional header/footer, item content = optional avatar + title/description meta + trailing actions, and a loading state. Tokens: white surface, border #E3E3E3, split #F1F1F1, radius-lg 12, bg-accent avatar, color-primary glyph, color-error danger action, text-default/secondary/tertiary. Motion bound to the shared motion tokens on persistent nodes. A deliberate, documented extension — not a measured match."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings",
    "audience"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     <aha-list> 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';      // <aha-icon>\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-list.js';   // <aha-list>\n</script>\n\n<!-- Structured rows via `items`: avatar + title/description meta + trailing actions.\n     size = small | default | large · bordered = outer border · split = row dividers (default on). -->\n<aha-list bordered list-title=\"Recent decks\" footer=\"3 of 24 decks\" style=\"max-width:360px\"\n  items='[\n    {\"title\":\"Team offsite 2026\",\"description\":\"12 slides · edited 2h ago\",\"avatar\":\"system-user-circle\",\n      \"actions\":[{\"key\":\"edit\",\"icon\":\"system-pencil-simple\",\"label\":\"Edit\"},{\"key\":\"delete\",\"icon\":\"system-trash\",\"danger\":true,\"label\":\"Delete\"}]},\n    {\"title\":\"Q3 product review\",\"description\":\"28 slides · edited yesterday\",\"avatar\":\"system-user-circle\",\n      \"actions\":[{\"key\":\"edit\",\"icon\":\"system-pencil-simple\",\"label\":\"Edit\"},{\"key\":\"delete\",\"icon\":\"system-trash\",\"danger\":true,\"label\":\"Delete\"}]}\n  ]'></aha-list>\n\n<!-- …or the free-form escape hatch: any light-DOM child becomes one plain row. -->\n<aha-list bordered list-title=\"Simple rows\" style=\"max-width:360px;margin-top:16px\">\n  <div>Polls</div>\n  <div>Quizzes</div>\n  <div>Word cloud</div>\n</aha-list>\n",
    "react": "import '@ahaslides-product/design/aha-list';   // registers <aha-list>\nimport '@ahaslides-product/design/icons';      // registers <aha-icon>\n\n// Structured rows: pass `items` (JSON) for avatar + title/description + trailing actions.\n// size = small | default | large · bordered = outer border · split = row dividers (default on).\nfunction DeckList({ title, decks }) {\n  return (\n    <aha-list\n      bordered\n      list-title={title}\n      footer={`${decks.length} decks`}\n      items={JSON.stringify(\n        decks.map((d) => ({\n          title: d.name,\n          description: d.meta,\n          avatar: 'system-user-circle',\n          actions: [\n            { key: 'edit', icon: 'system-pencil-simple', label: 'Edit' },\n            { key: 'delete', icon: 'system-trash', danger: true, label: 'Delete' },\n          ],\n        }))\n      )}\n      ref={(el) => el && (el.onaction = (e) => console.log(e.detail))}  // { key, index }\n    />\n  );\n}\n\n// usage\n<DeckList title=\"Recent decks\" decks={[{ name: 'Team offsite 2026', meta: '12 slides · edited 2h ago' }]} />\n",
    "vue": "// main.ts — register the elements + mark aha-* as custom elements\nimport '@ahaslides-product/design/aha-list';\nimport '@ahaslides-product/design/icons';   // registers <aha-icon>\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue\n<script setup>\nimport { ref, computed } from 'vue';\n// size = small | default | large · bordered = outer border · split = row dividers (default on).\nconst decks = ref([\n  { name: 'Team offsite 2026', meta: '12 slides · edited 2h ago' },\n  { name: 'Q3 product review', meta: '28 slides · edited yesterday' },\n]);\nconst items = computed(() => JSON.stringify(decks.value.map((d) => ({\n  title: d.name, description: d.meta, avatar: 'system-user-circle',\n  actions: [\n    { key: 'edit', icon: 'system-pencil-simple', label: 'Edit' },\n    { key: 'delete', icon: 'system-trash', danger: true, label: 'Delete' },\n  ],\n}))));\nconst onAction = (e) => console.log(e.detail);   // { key, index }\n</script>\n\n<template>\n  <aha-list bordered list-title=\"Recent decks\" :footer=\"`${decks.length} decks`\"\n    :items=\"items\" @action=\"onAction\" />\n</template>\n"
  }
}
