{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "diagram",
  "type": "registry:component",
  "title": "Diagram Kit",
  "description": "HTML/CSS block diagrams — rows, blocks with variants and tooltips, diamonds, brackets, notes, and a legend. Real DOM: selectable, screen-reader reachable, reflows.",
  "dependencies": [],
  "registryDependencies": [
    "https://mocoui.site/r/tokens.json"
  ],
  "files": [
    {
      "path": "registry/diagram/diagram.tsx",
      "type": "registry:component",
      "target": "components/moco/diagram.tsx",
      "content": "import * as React from \"react\";\nimport \"./diagram.css\";\n\n/**\n * HTML/CSS block diagrams. Real DOM, not SVG and not images: every label is\n * selectable text, reachable by a screen reader, and reflows on mobile.\n */\n\nexport interface DgmProps {\n  children: React.ReactNode;\n  minWidth?: number;\n  live?: boolean;\n}\n\nexport function Dgm({ children, minWidth, live }: DgmProps) {\n  return (\n    <div\n      className=\"moco-dgm\"\n      style={minWidth ? { minWidth } : undefined}\n      role=\"group\"\n      aria-live={live ? \"polite\" : undefined}\n    >\n      {children}\n    </div>\n  );\n}\n\nexport interface DgmRowProps {\n  label?: string;\n  children: React.ReactNode;\n  note?: React.ReactNode;\n}\n\nexport function DgmRow({ label, children, note }: DgmRowProps) {\n  return (\n    <>\n      <div className=\"moco-dgm-row\">\n        <div className=\"moco-dgm-row-label\">{label}</div>\n        <div className=\"moco-dgm-track\">{children}</div>\n      </div>\n      {note ? (\n        <div className=\"moco-dgm-row\" style={{ marginTop: \"-0.7rem\" }}>\n          <div />\n          <div className=\"moco-dgm-note\">{note}</div>\n        </div>\n      ) : null}\n    </>\n  );\n}\n\nexport type BlockVariant = \"default\" | \"active\" | \"dashed\" | \"warn\" | \"ghost\";\n\nexport interface DgmBlockProps {\n  label: React.ReactNode;\n  sub?: React.ReactNode;\n  variant?: BlockVariant;\n  tip?: string;\n  grow?: number;\n  id?: string;\n}\n\nexport function DgmBlock({\n  label,\n  sub,\n  variant = \"default\",\n  tip,\n  grow = 1,\n  id,\n}: DgmBlockProps) {\n  return (\n    <div\n      id={id}\n      className=\"moco-dgm-block\"\n      data-variant={variant}\n      style={{ flexGrow: grow }}\n      tabIndex={tip ? 0 : undefined}\n      title={tip}\n    >\n      <span className=\"moco-b-label\">{label}</span>\n      {sub ? <span className=\"moco-b-sub\">{sub}</span> : null}\n      {tip ? <span className=\"moco-dgm-tip\">{tip}</span> : null}\n    </div>\n  );\n}\n\nexport function DgmDiamond({ label }: { label?: string }) {\n  return (\n    <span\n      style={{ display: \"inline-flex\", alignItems: \"center\", flex: \"none\" }}\n      aria-label={label ? `marker: ${label}` : \"marker\"}\n    >\n      <span className=\"moco-dgm-diamond\" />\n      {label ? (\n        <span style={{ fontSize: 11.5, color: \"var(--moco-faint)\" }}>{label}</span>\n      ) : null}\n    </span>\n  );\n}\n\nexport interface DgmBracketProps {\n  children: React.ReactNode;\n  /** How many block-widths the bracket covers. */\n  span?: number;\n  /** How many block-widths to skip before it starts. */\n  offset?: number;\n  /** Total block-widths in the row above. */\n  total?: number;\n}\n\nexport function DgmBracket({ children, span = 1, offset = 0, total = 1 }: DgmBracketProps) {\n  return (\n    <div className=\"moco-dgm-row\">\n      <div />\n      <div style={{ display: \"flex\" }}>\n        {offset > 0 ? <div style={{ flex: offset }} /> : null}\n        <div style={{ flex: span }}>\n          <div className=\"moco-dgm-bracket\" />\n          <div className=\"moco-dgm-bracket-cap\">{children}</div>\n        </div>\n        {total - span - offset > 0 ? <div style={{ flex: total - span - offset }} /> : null}\n      </div>\n    </div>\n  );\n}\n\nexport function DgmNote({ children }: { children: React.ReactNode }) {\n  return (\n    <div className=\"moco-dgm-row\">\n      <div />\n      <div className=\"moco-dgm-note\">{children}</div>\n    </div>\n  );\n}\n\nexport interface DgmLegendProps {\n  items: { color: \"accent\" | \"warn\" | \"faint\" | \"ink\" | \"line\"; label: string }[];\n}\n\nexport function DgmLegend({ items }: DgmLegendProps) {\n  return (\n    <div className=\"moco-dgm-legend\">\n      {items.map((it) => (\n        <span\n          key={it.label}\n          style={{\n            color: it.color === \"accent\" ? \"var(--moco-accent-dk)\" : `var(--moco-${it.color})`,\n          }}\n        >\n          {/* The lime chip matches the filled block it stands for, but takes a\n              dark border — on paper the lime alone has no edge. */}\n          <span\n            className=\"moco-sw\"\n            style={{\n              background: it.color === \"accent\" ? \"var(--moco-accent)\" : \"transparent\",\n              borderColor: it.color === \"accent\" ? \"var(--moco-accent-dk)\" : undefined,\n            }}\n          />\n          <span style={{ color: \"var(--moco-faint)\" }}>{it.label}</span>\n        </span>\n      ))}\n    </div>\n  );\n}\n"
    },
    {
      "path": "registry/diagram/diagram.css",
      "type": "registry:file",
      "target": "components/moco/diagram.css",
      "content": ".moco-dgm {\n  display: grid;\n  gap: 1.1rem;\n  min-width: 460px;\n  font-size: 13px;\n  line-height: 1.4;\n}\n\n.moco-dgm-row {\n  display: grid;\n  grid-template-columns: 108px 1fr;\n  align-items: center;\n  gap: 1rem;\n}\n\n.moco-dgm-row-label {\n  color: var(--moco-faint);\n  font-size: 12px;\n  text-align: right;\n  letter-spacing: 0.02em;\n}\n\n.moco-dgm-track {\n  display: flex;\n  align-items: stretch;\n  gap: 6px;\n  flex-wrap: nowrap;\n}\n\n.moco-dgm-block {\n  position: relative;\n  flex: 1 1 0;\n  min-width: 0;\n  border: 1px solid var(--moco-line);\n  border-radius: 2px;\n  padding: 0.5rem 0.6rem;\n  background: var(--moco-bg);\n  color: var(--moco-body);\n  text-align: left;\n  transition:\n    opacity 200ms var(--moco-ease),\n    border-color 200ms var(--moco-ease),\n    background 200ms var(--moco-ease),\n    color 200ms var(--moco-ease);\n}\n\n.moco-dgm-block .moco-b-label {\n  display: block;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.moco-dgm-block .moco-b-sub {\n  display: block;\n  color: var(--moco-faint);\n  font-size: 11.5px;\n  margin-top: 2px;\n}\n\n.moco-dgm-block[data-variant=\"active\"] {\n  background: var(--moco-accent);\n  border-color: var(--moco-accent);\n  color: var(--moco-on-accent);\n}\n/* Sits on the lime fill in both themes, so the dark ink is safe hardcoded. */\n.moco-dgm-block[data-variant=\"active\"] .moco-b-sub {\n  color: rgba(20, 24, 10, 0.72);\n}\n\n.moco-dgm-block[data-variant=\"warn\"] {\n  border-color: var(--moco-warn);\n  color: var(--moco-warn);\n  background: var(--moco-warn-wash);\n}\n.moco-dgm-block[data-variant=\"warn\"] .moco-b-sub {\n  color: var(--moco-warn);\n  opacity: 0.72;\n}\n\n.moco-dgm-block[data-variant=\"dashed\"] {\n  border-style: dashed;\n  background: transparent;\n  color: var(--moco-faint);\n}\n\n.moco-dgm-block[data-variant=\"ghost\"] {\n  border-color: transparent;\n  background: transparent;\n  color: var(--moco-faint);\n}\n\n/* Hover: dim siblings. */\n.moco-dgm-track:has(.moco-dgm-block:hover) .moco-dgm-block:not(:hover),\n.moco-dgm-track:has(.moco-dgm-block:focus-visible) .moco-dgm-block:not(:focus-visible) {\n  opacity: 0.4;\n}\n\n.moco-dgm-tip {\n  position: absolute;\n  bottom: calc(100% + 8px);\n  left: 0;\n  z-index: 5;\n  width: max-content;\n  max-width: 240px;\n  background: var(--moco-bg);\n  border: 1px solid var(--moco-line);\n  border-radius: 2px;\n  padding: 0.45rem 0.6rem;\n  font-size: 12px;\n  color: var(--moco-muted);\n  opacity: 0;\n  pointer-events: none;\n  transition: opacity 150ms var(--moco-ease);\n}\n\n.moco-dgm-block:hover .moco-dgm-tip,\n.moco-dgm-block:focus-visible .moco-dgm-tip {\n  opacity: 1;\n}\n\n.moco-dgm-diamond {\n  width: 7px;\n  height: 7px;\n  border: 1px solid var(--moco-accent-dk);\n  transform: rotate(45deg);\n  display: inline-block;\n  margin: 0 0.4rem;\n  flex: none;\n}\n\n.moco-dgm-bracket {\n  border-top: 1px solid var(--moco-line);\n  border-left: 1px solid var(--moco-line);\n  border-right: 1px solid var(--moco-line);\n  height: 8px;\n  margin-top: 4px;\n}\n\n.moco-dgm-bracket-cap {\n  font-size: 12px;\n  color: var(--moco-faint);\n  text-align: center;\n  margin-top: 6px;\n}\n\n.moco-dgm-note {\n  color: var(--moco-faint);\n  font-size: 12px;\n  grid-column: 2;\n}\n\n.moco-dgm-legend {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.35rem 1.25rem;\n  font-size: 12px;\n  color: var(--moco-faint);\n  border-top: 1px solid var(--moco-line);\n  padding-top: 0.9rem;\n}\n\n.moco-dgm-legend span.moco-sw {\n  display: inline-block;\n  width: 9px;\n  height: 9px;\n  border: 1px solid currentColor;\n  margin-right: 0.45rem;\n  vertical-align: -1px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .moco-dgm-block,\n  .moco-dgm-tip {\n    transition-duration: 0.001ms;\n  }\n}\n"
    }
  ],
  "docs": "import * as React from \"react\";\nimport {\n  Dgm,\n  DgmRow,\n  DgmBlock,\n  DgmDiamond,\n  DgmBracket,\n  DgmNote,\n  DgmLegend,\n} from \"./diagram\";\n\nexport default function DiagramDemo() {\n  return (\n    <div style={{ overflowX: \"auto\" }}>\n      <Dgm minWidth={520}>\n        <DgmRow label=\"request\">\n          <DgmBlock label=\"Client\" sub=\"browser\" />\n          <DgmDiamond label=\"tls\" />\n          <DgmBlock label=\"Edge\" variant=\"active\" tip=\"Terminates TLS, caches static assets\" />\n          <DgmBlock label=\"Origin\" sub=\"app server\" grow={2} />\n        </DgmRow>\n        <DgmRow label=\"failure\" note=\"Retries stop after the third attempt.\">\n          <DgmBlock label=\"Queue\" variant=\"dashed\" />\n          <DgmBlock label=\"Dead letter\" variant=\"warn\" />\n          <DgmBlock label=\"(unused)\" variant=\"ghost\" />\n        </DgmRow>\n        <DgmBracket span={2} offset={1} total={3}>\n          retry path\n        </DgmBracket>\n        <DgmNote>Every label here is selectable text.</DgmNote>\n        <DgmLegend\n          items={[\n            { color: \"accent\", label: \"hot path\" },\n            { color: \"warn\", label: \"failure\" },\n            { color: \"faint\", label: \"optional\" },\n          ]}\n        />\n      </Dgm>\n    </div>\n  );\n}\n",
  "meta": {
    "tags": [
      "diagram",
      "layout",
      "accessibility"
    ]
  }
}