{
  "generatedFrom": "icon.contract.json",
  "component": "Icon",
  "slug": "icon",
  "group": "General",
  "tier": "leaf-lit",
  "summary": "One glyph set, called by name — 259 icons imported from Figma, rendered by the shared <aha-icon>, never inline SVG.",
  "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/icons';",
    "element": "aha-icon",
    "registers": "aha-icon"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/icon/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/icon/icon.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/icon.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/icon.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-icon> 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-icon"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-icon"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-icon",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "name",
      "type": "string",
      "default": "—",
      "desc": "Registry glyph name, e.g. system-bell, slidetype-poll, filetype-course"
    },
    {
      "name": "size",
      "type": "12 | 16 | 24 | 32",
      "default": "24",
      "desc": "On-grid pixel size; the master stroke scales with it"
    },
    {
      "name": "label",
      "type": "string",
      "default": "—",
      "desc": "Accessible name (role=img). Omit for a decorative icon"
    },
    {
      "name": "decorative",
      "type": "boolean",
      "default": "false",
      "desc": "aria-hidden — for an icon that only repeats adjacent text"
    }
  ],
  "tokens": [
    "color-error"
  ],
  "spec": [
    {
      "label": "Set",
      "value": "259 glyphs · system · slide-type · file-type"
    },
    {
      "label": "Source",
      "value": "Figma Design System V3 · node 50699-7126"
    },
    {
      "label": "Sizes",
      "value": "12 · 16 · 24 · 32 (only)"
    },
    {
      "label": "Colour",
      "value": "currentColor / semantic token (254 recolorable)"
    },
    {
      "label": "State",
      "value": "outline = neutral · -filled asset = active"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "system-* glyph",
        "when": "the default for all product-UI chrome, buttons, menus, list rows, status"
      },
      {
        "what": "-filled asset",
        "when": "a selected/active/on state — e.g. system-bookmark-simple-filled; a solid glyph survives greyscale"
      },
      {
        "what": "slide-type / file-type",
        "when": "labelling a slide kind or a file kind; file-type glyphs keep their baked brand colour"
      }
    ],
    "note": "Call by name from the registry — never inline an <svg>, never pull a second icon set (Lucide/Heroicons/FontAwesome/@ant-design/icons). Off-grid sizes (no 20px) aren't supported. Icon-only buttons need an aria-label (and a tooltip when the meaning isn't obvious). If a glyph is genuinely missing, add the SVG under icons/svg and re-run build-icons.mjs."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings",
    "audience"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     Call any glyph BY NAME — never inline an <svg>. One import loads <aha-icon> +\n     the 259-glyph registry; colour follows currentColor, size is 12 | 16 | 24 | 32. -->\n<script type=\"module\">\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/icons.js';   // registers <aha-icon> + registry\n</script>\n\n<!-- Icon + text — match the label's cap height (16 beside body text), glyph leading. -->\n<button style=\"display:inline-flex; align-items:center; gap:8px\">\n  <aha-icon name=\"system-plus\" size=\"16\" decorative></aha-icon>\n  Add slide\n</button>\n\n<!-- Icon-only — MUST carry an accessible name (+ a tooltip when the glyph isn't obvious). -->\n<button aria-label=\"Search\" title=\"Search\">\n  <aha-icon name=\"system-magnifying-glass\" size=\"16\" decorative></aha-icon>\n</button>\n\n<!-- Colour is set on the wrapper; the glyph inherits it via currentColor. State = -filled asset. -->\n<span style=\"color: var(--aha-color-primary, #6A1EBB)\">\n  <aha-icon name=\"system-bookmark-simple-filled\" size=\"24\" label=\"Saved\"></aha-icon>\n</span>\n",
    "react": "import '@ahaslides-product/design/icons';   // registers <aha-icon> + loads the glyph registry (259 icons)\n\n// Call any glyph BY NAME — never inline an <svg>. Browse names in the Icon library,\n// or read icons.agent.json / icons.llms.txt. Colour follows currentColor; size is 12/16/24/32.\n\n// Icon-only button — MUST carry an accessible name (+ a tooltip when the glyph isn't obvious).\n<button aria-label=\"Search\" title=\"Search\">\n  <aha-icon name=\"system-magnifying-glass\" size={16} decorative />\n</button>\n\n// Icon + text — match the label's cap height (16 beside body text), glyph on the leading side.\n<button className=\"add\">\n  <aha-icon name=\"system-plus\" size={16} decorative />\n  Add slide\n</button>\n\n// State: outline = neutral, filled = active (use the dedicated -filled asset).\n// Colour is set on the wrapper — the glyph inherits it via currentColor.\n<span style={{ color: 'var(--aha-color-primary)' }}>\n  <aha-icon name={saved ? 'system-bookmark-simple-filled' : 'system-bookmark-simple'} size={24} label=\"Save\" />\n</span>\n\n// Slide-type / file-type families are the same call, different name:\n<aha-icon name=\"slidetype-poll\" size={24} label=\"Poll\" />\n<aha-icon name=\"filetype-course\" size={24} label=\"Course\" />\n",
    "vue": "// main.ts — register the element + registry, and mark aha-* as custom elements\nimport '@ahaslides-product/design/icons';   // registers <aha-icon> + loads the glyph registry (259 icons)\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue — presenter-app renders every glyph through the shared Icon, BY NAME.\n// Browse names in the Icon library / icons.llms.txt. Colour follows currentColor; size 12/16/24/32.\n<template>\n  <!-- Icon-only button — MUST have an accessible name (+ tooltip when unclear) -->\n  <button aria-label=\"Settings\" title=\"Settings\">\n    <aha-icon name=\"system-gear\" :size=\"16\" decorative />\n  </button>\n\n  <!-- Icon + text — cap-height match, 4px gap, glyph leading -->\n  <button class=\"add\">\n    <aha-icon name=\"system-plus\" :size=\"16\" decorative />\n    Add slide\n  </button>\n\n  <!-- State: outline ↔ -filled asset is the toggle; colour = currentColor on the wrapper -->\n  <span :style=\"{ color: 'var(--aha-color-primary)' }\">\n    <aha-icon :name=\"saved ? 'system-bookmark-simple-filled' : 'system-bookmark-simple'\" :size=\"24\" label=\"Save\" />\n  </span>\n\n  <!-- Slide-type / file-type families are the same call, different name -->\n  <aha-icon name=\"slidetype-word-cloud\" :size=\"24\" label=\"Word cloud\" />\n  <aha-icon name=\"filetype-lesson\" :size=\"24\" label=\"Lesson\" />\n</template>\n"
  }
}
