{
  "generatedFrom": "color-picker.contract.json",
  "component": "Color picker",
  "slug": "color-picker",
  "group": "Data Entry",
  "tier": "leaf-lit",
  "summary": "Pick a colour from a selectable palette of presets.",
  "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-color-picker';",
    "element": "aha-color-picker",
    "registers": "aha-color-picker"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/color-picker/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/color-picker/color-picker.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/color-picker.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/color-picker.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-color-picker> 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-color-picker"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-color-picker"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-color-picker",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "value",
      "type": "string",
      "default": "#6A1EBB",
      "desc": "Selected colour (hex) — its swatch is ringed + checked"
    },
    {
      "name": "swatches",
      "type": "string",
      "default": "brand ramp (12)",
      "desc": "Pipe-separated hex presets, e.g. \"#6A1EBB|#FF4081\""
    },
    {
      "name": "size",
      "type": "'small' | 'default' | 'large'",
      "default": "default",
      "desc": "Scales trigger + swatch dimensions"
    },
    {
      "name": "disabled",
      "type": "boolean",
      "default": "false",
      "desc": "Greys + inerts the whole control"
    },
    {
      "name": "open",
      "type": "boolean",
      "default": "false",
      "desc": "Panel open state; reflected attribute"
    },
    {
      "name": "change",
      "type": "CustomEvent<{value}>",
      "default": "—",
      "desc": "Composed event; read e.detail.value"
    }
  ],
  "tokens": [
    "bg-container",
    "bg-container-disabled",
    "bg-elevated",
    "border",
    "border-hover",
    "border-disabled",
    "text-default",
    "text-inverse",
    "text-disabled",
    "color-primary",
    "radius-sm",
    "radius-xs",
    "radius-default",
    "font-product",
    "motion-mid",
    "motion-fast",
    "ease-in-out",
    "ease-out"
  ],
  "spec": [
    {
      "label": "Trigger",
      "value": "1px border #E3E3E3, radius 6; current swatch 16/20/24 by size (radius 4)"
    },
    {
      "label": "Panel",
      "value": "bg-elevated #FFFFFF, radius 8, 4-col swatch grid"
    },
    {
      "label": "Swatch",
      "value": "22/28/34 by size, radius 4; selected ringed color-primary + check glyph"
    },
    {
      "label": "Selected",
      "value": "aria-pressed=true, .on ring + system-check (dark on pale chips)"
    },
    {
      "label": "Disabled",
      "value": "bg-container-disabled fill, border-disabled, not-allowed, inert"
    },
    {
      "label": "Motion",
      "value": "panel fade + lift; swatch hover scale; check fade (ease-out)"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Color picker",
        "when": "choosing a brand or theme colour from a curated set"
      },
      {
        "what": "Segmented",
        "when": "picking a labelled option rather than a colour"
      },
      {
        "what": "Input",
        "when": "an arbitrary free-form value is genuinely needed"
      }
    ],
    "note": "Prefer a curated palette over a free spectrum — on-brand results, fewer accessibility misses. Show the current value beside the trigger so the choice is legible.",
    "dsv3": "DS V3 has no dedicated Color-picker component-set — the selectable-swatch palette is composed from the shared DS V3 primitives: the standard control border, radii (sm trigger, default panel, xs swatch) and elevation, the color-primary selection ring, the small/default/large control-height sizing convention, and the disabled surface tokens. The selected swatch carries a system-check glyph (from the DS icon library) and aria-pressed synced to selection. Panel fade + lift, swatch hover-scale and the check fade animate on persistent nodes via the shared motion tokens."
  },
  "surfaces": [
    "editor",
    "dashboard",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     <aha-color-picker> is the SAME shared custom element React and Vue consume.\n     Defaults to the brand ramp; override with swatches=\"#hex|#hex\". size = small|default|large,\n     disabled greys the control. The swatch matching value is ringed + checked. Emits a composed `change`. -->\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> — the selected-swatch check glyph\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-color-picker.js';   // registers <aha-color-picker>\n</script>\n\n<aha-color-picker id=\"pick\" value=\"#6A1EBB\" size=\"default\"></aha-color-picker>\n<aha-color-picker value=\"#FF4081\" size=\"small\"></aha-color-picker>\n<aha-color-picker value=\"#20E8B5\" size=\"large\"></aha-color-picker>\n<aha-color-picker value=\"#6A1EBB\" disabled></aha-color-picker>\n<aha-color-picker value=\"#0FB5C4\" swatches=\"#0FB5C4|#6A1EBB|#FF4081|#1A1A1A\"></aha-color-picker>\n\n<script>\n  // Plain DOM — no framework. Read e.detail.value off the composed CustomEvent.\n  document.getElementById('pick').addEventListener('change', (e) => {\n    console.log('colour:', e.detail.value);\n  });\n</script>\n",
    "react": "import '@ahaslides-product/design/icons';            // <aha-icon> — the selected-swatch check glyph\nimport '@ahaslides-product/design/aha-color-picker';   // registers <aha-color-picker>\nimport { useRef, useEffect } from 'react';\n\n// React 18 needs a thin wrapper; React 19 can use <aha-color-picker> directly.\nfunction AhaColorPicker({ value, swatches, size, disabled, onChange }) {\n  const ref = useRef();\n  useEffect(() => {\n    const el = ref.current;\n    if (value) el.value = value;\n    const h = (e) => onChange?.(e.detail.value);   // composed CustomEvent\n    el.addEventListener('change', h);\n    return () => el.removeEventListener('change', h);\n  });\n  return <aha-color-picker ref={ref} swatches={swatches} size={size} disabled={disabled || undefined} />;\n}\n\n// usage\n<AhaColorPicker value={colour} size=\"large\" onChange={setColour} />\n",
    "vue": "// main.ts — register the element + mark aha-* as custom elements\nimport '@ahaslides-product/design/icons';            // <aha-icon> — the selected-swatch check glyph\nimport '@ahaslides-product/design/aha-color-picker';\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue\n<script setup>\nimport { ref } from 'vue';\nconst colour = ref('#6A1EBB');\n</script>\n\n<template>\n  <aha-color-picker\n    :value.prop=\"colour\"\n    size=\"large\"\n    @change=\"colour = $event.detail.value\"\n  />\n</template>\n"
  }
}
