{
  "name": "NarrationLog",
  "package": "@magicblocksai/ui",
  "file": "packages/ui/src/components/NarrationLog.tsx",
  "chapterTag": "17 AI Surfaces",
  "chapter": "17-app-ai.html",
  "sectionId": "narration-log",
  "elName": "NarrationLog &mdash; scan in progress",
  "demoUrl": "https://brand.magicblocks.ai/components/17-app-ai#narration-log",
  "hasLiveDemo": false,
  "description": "Event-log / scan-narration list. Vertical hairline list with status-coloured\nrows for any long-running async process (scan, build, deploy, sync).",
  "useClient": true,
  "interactivity": "interactive",
  "namedExports": [
    {
      "name": "NarrationLog",
      "isPrincipal": true,
      "isType": false
    },
    {
      "name": "NarrationLogProps",
      "isPrincipal": false,
      "isType": true
    },
    {
      "name": "NarrationLogItem",
      "isPrincipal": false,
      "isType": true
    },
    {
      "name": "NarrationLogStatus",
      "isPrincipal": false,
      "isType": false
    }
  ],
  "importStatement": "import { NarrationLog } from \"@magicblocksai/ui\";",
  "props": [
    {
      "name": "items",
      "optional": false,
      "type": "NarrationLogItem[]",
      "doc": "Log items, ordered oldest → newest. The component renders them in insertion order; consumers driving a live SSE feed typically `append` rather than `unshift`."
    },
    {
      "name": "maxVisible",
      "optional": true,
      "type": "number",
      "doc": "When set, only the last `maxVisible` items render; the rest collapse behind a \"show N earlier\" toggle. Omit (or pass `0`) to render every item."
    },
    {
      "name": "enterAnimation",
      "optional": true,
      "type": "\"none\" | \"slide-fade\"",
      "doc": "Enter-animation modifier. `\"slide-fade\"` adds a 4px translate-up + opacity fade on each row's mount. Honours `prefers-reduced-motion` via the CSS — no JS-side guard needed."
    },
    {
      "name": "glyphFor",
      "optional": true,
      "type": "(status: NarrationLogStatus) => ReactNode | null",
      "doc": "Override the per-status glyph (default: blank / `✓` / `!` / `✗`). Pass `null` to suppress the glyph slot entirely."
    },
    {
      "name": "expandLabel",
      "optional": true,
      "type": "(hiddenCount: number) => ReactNode",
      "doc": "Label for the expand toggle. Receives the hidden count."
    }
  ],
  "classesUsed": [
    "narration-log",
    "narration-log-item",
    "narration-log-item-glyph",
    "narration-log-item-text",
    "narration-log-toggle"
  ],
  "examples": {
    "react": "<NarrationLog\n  items={[\n    { id: '1', text: 'Scanning yourcompany.com…', status: 'info' },\n    { id: '6', text: 'Privacy policy missing SMS consent disclosure', status: 'fail' },\n    { id: '8', text: 'Domain is branded — no URL shorteners detected', status: 'pass' },\n  ]}\n  maxVisible={15}\n  enterAnimation=\"slide-fade\"\n/>",
    "html": "<div class=\"narration-log-demo\">\n  <ol class=\"narration-log\" data-anim=\"slide-fade\">\n    <li class=\"narration-log-item\" data-status=\"info\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">·</span>\n      <span class=\"narration-log-item-text\">Scanning yourcompany.com&hellip;</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"info\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">·</span>\n      <span class=\"narration-log-item-text\">Resolved 14 internal links</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"info\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">·</span>\n      <span class=\"narration-log-item-text\">Found privacy policy at /privacy</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"pass\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">&check;</span>\n      <span class=\"narration-log-item-text\">Site is HTTPS</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"pass\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">&check;</span>\n      <span class=\"narration-log-item-text\">Domain is branded &mdash; no URL shorteners detected</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"warn\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">!</span>\n      <span class=\"narration-log-item-text\">Terms-of-service page returns 302 redirect</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"fail\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">&#x2717;</span>\n      <span class=\"narration-log-item-text\">Privacy policy missing SMS consent disclosure</span>\n    </li>\n    <li class=\"narration-log-item\" data-status=\"info\">\n      <span class=\"narration-log-item-glyph\" aria-hidden=\"true\">·</span>\n      <span class=\"narration-log-item-text\">Scan complete &mdash; 5 of 7 checks passed</span>\n    </li>\n  </ol>\n</div>",
    "css": ".narration-log {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 4px;\n  font: 400 13px/1.45 var(--f-body);\n}\n\n.narration-log-item {\n  display: flex;\n  align-items: baseline;\n  gap: var(--s-2);\n  padding: 6px var(--s-3);\n  border-radius: var(--r-xs);\n  color: var(--fg);\n  background: transparent;\n}\n\n.narration-log-item-glyph {\n  font: 500 11px/1 var(--f-mono);\n  display: inline-block;\n  width: 14px; text-align: center;\n  flex: 0 0 14px;\n  opacity: 0.85;\n}\n\n.narration-log-item-text { flex: 1; min-width: 0; }\n\n.narration-log-toggle {\n  appearance: none;\n  background: transparent;\n  border: 0;\n  padding: 4px var(--s-3);\n  font: 500 12px/1 var(--f-mono);\n  text-transform: uppercase;\n  letter-spacing: 0.06em;\n  color: var(--fg-dim);\n  cursor: pointer;\n  border-radius: var(--r-xs);\n  align-self: flex-start;\n}"
  }
}
