{
  "generatedFrom": "user-info.contract.json",
  "component": "User info",
  "slug": "user-info",
  "group": "Data Display",
  "tier": "leaf-lit",
  "summary": "A person/identity row — an avatar next to a name, with an optional email underneath.",
  "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-user-info';",
    "element": "aha-user-info",
    "registers": "aha-user-info"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/user-info/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/user-info/user-info.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/user-info.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/user-info.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-user-info> 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-user-info"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-user-info"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-user-info",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "name",
      "type": "string",
      "default": "—",
      "desc": "The person's full name — rendered as text, and passed to the avatar for initials/alt"
    },
    {
      "name": "email",
      "type": "string",
      "default": "—",
      "desc": "Optional email; when present (and not compact) it renders under the name in the default layout"
    },
    {
      "name": "src",
      "type": "string",
      "default": "—",
      "desc": "Avatar image URL; falls through to initials of `name` when absent"
    },
    {
      "name": "size",
      "type": "'default' | 'compact'",
      "default": "default",
      "desc": "'default' → 40px avatar + email row; 'compact' → 24px avatar + name only. Omitting `email` implies compact"
    }
  ],
  "tokens": [
    "text-default",
    "text-tertiary",
    "font-product"
  ],
  "spec": [
    {
      "label": "Layout",
      "value": "avatar + (name over email) · gap 8"
    },
    {
      "label": "Name",
      "value": "14px · SemiBold 600 · text-default #1A1A1A"
    },
    {
      "label": "Email",
      "value": "12px · Regular 400 · text-secondary #8A8A8A"
    },
    {
      "label": "Avatar",
      "value": "40 when email shown · 24 name-only (reuses <aha-avatar>)"
    },
    {
      "label": "Compact",
      "value": "size=\"compact\" (or no email) → 24px avatar + name only"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "User info",
        "when": "showing a person's identity as a row — avatar + name (+ email): a member list, an author byline, an account switcher"
      },
      {
        "what": "Avatar",
        "when": "just the picture/initials with no name text beside it"
      },
      {
        "what": "Descriptions",
        "when": "a labelled field grid about an entity, not a compact identity row"
      }
    ],
    "note": "Always provide `name` — it's both the visible label and the avatar's initials/alt. Reach for User info over a plain Avatar whenever the name (and email) belong next to the face; reach for the bare Avatar when only the picture is wanted. Omit `email` (or set size=\"compact\") for a tight one-line identity in menus and dense lists.",
    "dsv3": "COVERED — the DS V3 User info component (fileKey P764iQ6y4ZwW7W3f7FLZyW, node 2684:2721): Email=Yes shows avatar + name + email (40px avatar), Email=No shows avatar + name only (24px avatar). Name = 14px / SemiBold 600 / #1A1A1A (text-default); email = 12px / Regular 400 / #8A8A8A (text-secondary); gap 8. No visible card border (the dashed box in the mock is a Figma annotation) — spacing only. Reuses the shared Avatar for the picture/initials rather than re-drawing one."
  },
  "surfaces": [
    "dashboard",
    "settings",
    "editor",
    "audience"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     <aha-user-info> is the SAME shared custom element React and Vue consume — here in its native\n     form. It REUSES the shared <aha-avatar> for the picture/initials. Theming comes only from the\n     --aha-* tokens in tokens.css. `name` is required; `email` is optional (omit → compact,\n     name-only, 24px avatar); `src` sets the avatar photo; `size` is 'default' | 'compact'. -->\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> (avatar glyph fallback)\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-user-info.js';  // registers <aha-user-info> (+ <aha-avatar>)\n</script>\n\n<div style=\"display:flex; flex-direction:column; gap:16px; align-items:flex-start\">\n  <!-- Default: avatar + name + email (40px avatar) -->\n  <aha-user-info name=\"Brian Le\" email=\"brian@ahaslides.com\"></aha-user-info>\n\n  <!-- With a photo -->\n  <aha-user-info name=\"Grace Hopper\" email=\"grace@ahaslides.com\" src=\"https://i.pravatar.cc/80?img=5\"></aha-user-info>\n\n  <!-- Compact / name-only (24px avatar) — omit email, or set size=\"compact\" -->\n  <aha-user-info name=\"Ada Lovelace\"></aha-user-info>\n</div>\n",
    "react": "import '@ahaslides-product/design/aha-user-info';   // registers <aha-user-info> (+ <aha-avatar>)\n\n// A plain custom element — no wrapper needed for static props. It reuses the shared <aha-avatar>\n// internally, so you never hand-roll an avatar beside a name. Omit `email` (or size=\"compact\")\n// for the tight, name-only row.\nfunction AhaUserInfo({ name, email, src, size = 'default' }) {\n  return <aha-user-info name={name} email={email} src={src} size={size} />;\n}\n\n// usage\n<AhaUserInfo name=\"Brian Le\" email=\"brian@ahaslides.com\" />\n<AhaUserInfo name=\"Grace Hopper\" email=\"grace@ahaslides.com\" src=\"/u/grace.jpg\" />\n<AhaUserInfo name=\"Ada Lovelace\" />                          {/* compact / name-only */}\n",
    "vue": "// main.ts — register the element + mark aha-* as custom elements\nimport '@ahaslides-product/design/aha-user-info';   // <aha-user-info> (+ <aha-avatar>)\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue\n<template>\n  <!-- Default: avatar + name + email -->\n  <aha-user-info name=\"Brian Le\" email=\"brian@ahaslides.com\" />\n\n  <!-- With a photo -->\n  <aha-user-info name=\"Grace Hopper\" email=\"grace@ahaslides.com\" :src=\"photoUrl\" />\n\n  <!-- Compact / name-only — omit email, or set size=\"compact\" -->\n  <aha-user-info name=\"Ada Lovelace\" />\n</template>\n"
  }
}
