/* components-data.jsx — component catalog (bilingual EN / 中文), assembled from the
   authoring workflow. EDITABLE article layer (summary/status/overview/usage/examples)
   vs READ-ONLY (props/changelog, from code). c.wired === true → the component has a live
   demo, component-layer tokens, and a node in the relationship graph. */
const COMPONENTS = [
  {
    "id": "button",
    "name": "Button",
    "nameZh": "按钮",
    "category": "Foundation",
    "categoryZh": "基础",
    "status": "stable",
    "caution": true,
    "cautionReason": "Button is consumed by every product surface and embedded in dozens of compound components (forms, toolbars, modals, dialogs); changing its sizing, focus ring, or variant tokens ripples across all four brand themes.",
    "cautionReasonZh": "按钮被每一个产品界面使用，并嵌入数十个复合组件中（表单、工具栏、模态框、对话框）；改动其尺寸、焦点环或变体 token 会波及全部四套品牌主题。",
    "icon": "component",
    "summary": "The primary interactive trigger for actions, submissions, and navigation across all surfaces.",
    "summaryZh": "用于触发操作、提交和导航的主要交互按钮，适用于所有界面。",
    "tags": [
      "action",
      "form",
      "interactive",
      "core"
    ],
    "overview": "Button is the canonical action trigger and should map intent to variant: use the primary variant (accent.default fill) for the single most important action per view, secondary for supporting actions, and ghost for low-emphasis or toolbar use. Sizing keys off spacing.inset.md and radius.control so buttons stay visually consistent with inputs and selects. Always pair a clear label with an optional leading icon; icon-only buttons must carry an accessible label via the ariaLabel prop.",
    "overviewZh": "按钮是标准的操作触发器，应将意图映射到变体：每个视图中最重要的单个操作使用主要变体（accent.default 填充），辅助操作使用次要变体，低强调或工具栏场景使用幽灵变体。尺寸取自 spacing.inset.md 与 radius.control，使按钮在视觉上与输入框、选择框保持一致。始终为按钮配清晰的文案与可选的前置图标；纯图标按钮必须通过 ariaLabel 属性提供无障碍标签。",
    "dos": [
      "Reserve the primary variant for the single most important action in a view.",
      "Keep labels to a verb or verb-noun phrase ('Save', 'Run analysis') so intent is scannable.",
      "Show a loading state for async actions and disable the button while pending."
    ],
    "dosZh": [
      "每个视图中仅将主要变体保留给最重要的单个操作。",
      "文案保持为动词或动宾短语（'保存'、'运行分析'），让意图易于扫读。",
      "异步操作时显示加载状态，并在处理期间禁用按钮。"
    ],
    "donts": [
      "Don't stack multiple primary buttons in the same action group.",
      "Don't use a button for navigation between pages — use Link instead.",
      "Don't ship icon-only buttons without an ariaLabel."
    ],
    "dontsZh": [
      "不要在同一操作组中堆叠多个主要按钮。",
      "不要用按钮做页面间导航——请改用文字链接。",
      "不要发布缺少 ariaLabel 的纯图标按钮。"
    ],
    "examples": [
      {
        "id": "button-variants",
        "title": "Variants",
        "titleZh": "变体",
        "note": "Primary, secondary, ghost, and danger variants side by side.",
        "noteZh": "主要、次要、幽灵与危险变体并排展示。",
        "show": true,
        "demo": "button-variants"
      },
      {
        "id": "button-sizes",
        "title": "Sizes & loading",
        "titleZh": "尺寸与加载",
        "note": "sm / md / lg sizes plus the async loading state.",
        "noteZh": "sm / md / lg 三档尺寸以及异步加载状态。",
        "show": true,
        "demo": "button-sizes"
      },
      {
        "id": "button-icon",
        "title": "With icons",
        "titleZh": "带图标",
        "note": "Leading and icon-only buttons with accessible labels.",
        "noteZh": "带前置图标及纯图标按钮，均附无障碍标签。",
        "show": false,
        "demo": "button-icon"
      }
    ],
    "props": [
      {
        "name": "variant",
        "type": "'primary' | 'secondary' | 'ghost' | 'danger'",
        "def": "'secondary'",
        "required": false,
        "desc": "Visual emphasis level that maps to a token set.",
        "descZh": "视觉强调级别，映射到对应的 token 组。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg'",
        "def": "'md'",
        "required": false,
        "desc": "Controls height and inset padding via spacing.inset.",
        "descZh": "通过 spacing.inset 控制高度与内边距。"
      },
      {
        "name": "loading",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Shows a spinner and disables interaction while pending.",
        "descZh": "处理期间显示加载指示器并禁用交互。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Disables the button and applies muted token styling.",
        "descZh": "禁用按钮并应用置灰 token 样式。"
      },
      {
        "name": "iconLeft",
        "type": "ReactNode",
        "def": "undefined",
        "required": false,
        "desc": "Optional leading icon rendered before the label.",
        "descZh": "可选的前置图标，渲染于文案之前。"
      },
      {
        "name": "ariaLabel",
        "type": "string",
        "def": "undefined",
        "required": false,
        "desc": "Accessible label, required when the button is icon-only.",
        "descZh": "无障碍标签，纯图标按钮时为必填。"
      },
      {
        "name": "onClick",
        "type": "(e: MouseEvent) => void",
        "def": "undefined",
        "required": false,
        "desc": "Click handler invoked when the button is activated.",
        "descZh": "按钮被激活时调用的点击回调。"
      }
    ],
    "changelog": [
      {
        "v": "3.2.0",
        "date": "2026-04-18",
        "notes": [
          "Added danger variant mapped to color.feedback.error.",
          "Refined focus ring to use accent.focus for AA contrast."
        ],
        "notesZh": [
          "新增危险变体，映射到 color.feedback.error。",
          "优化焦点环改用 accent.focus 以满足 AA 对比度。"
        ]
      },
      {
        "v": "3.1.0",
        "date": "2026-02-03",
        "notes": [
          "Introduced loading state with inline spinner."
        ],
        "notesZh": [
          "引入带内联加载指示器的 loading 状态。"
        ]
      }
    ],
    "repo": "packages/ui/src/Button.tsx",
    "version": "3.2.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "3 days ago",
    "lastCommit": "a3f9c21",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "scrollbar",
    "name": "Scrollbar",
    "nameZh": "滚动条",
    "category": "Foundation",
    "categoryZh": "基础",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "move",
    "summary": "A themed, cross-platform scrollbar that overlays scrollable regions without reflowing content.",
    "summaryZh": "贴合主题的跨平台滚动条，覆盖可滚动区域而不引起内容回流。",
    "tags": [
      "layout",
      "overflow",
      "utility"
    ],
    "overview": "Scrollbar normalizes native scrollbar appearance across macOS, Windows, and embedded HMI browsers so dense dashboards and data tables look consistent. The track stays transparent and the thumb uses color.border.strong with radius.control, fading in on hover to keep focus on content. Apply it to any scrollable container rather than relying on OS chrome, especially in fullscreen equipment HMIs where native bars are hidden.",
    "overviewZh": "滚动条统一了 macOS、Windows 及嵌入式 HMI 浏览器中原生滚动条的外观，使密集的仪表盘与数据表格保持一致。轨道保持透明，滑块采用 color.border.strong 配合 radius.control，在悬停时淡入以保持对内容的聚焦。请将其应用于任何可滚动容器，而非依赖系统外观，尤其是在原生滚动条被隐藏的全屏设备 HMI 中。",
    "dos": [
      "Wrap long lists and data tables so the scroll affordance matches the theme.",
      "Use the overlay mode in dense layouts to avoid stealing horizontal space.",
      "Let the thumb fade in on hover to keep idle surfaces calm."
    ],
    "dosZh": [
      "包裹长列表与数据表格，使滚动样式与主题一致。",
      "在密集布局中使用覆盖模式，避免占用横向空间。",
      "让滑块在悬停时淡入，保持空闲界面整洁。"
    ],
    "donts": [
      "Don't hide the scrollbar entirely on touch-and-mouse hybrid HMI panels.",
      "Don't override the thumb color with hard-coded values — use border tokens.",
      "Don't nest scrollbars within scrollbars for the same axis."
    ],
    "dontsZh": [
      "不要在触控与鼠标混合的 HMI 面板上完全隐藏滚动条。",
      "不要用硬编码值覆盖滑块颜色——请使用 border 系列 token。",
      "不要在同一轴向上嵌套多个滚动条。"
    ],
    "examples": [
      {
        "id": "scrollbar-overlay",
        "title": "Overlay mode",
        "titleZh": "覆盖模式",
        "note": "Thumb overlays content and fades in on hover.",
        "noteZh": "滑块覆盖在内容之上，悬停时淡入。",
        "show": true,
        "demo": "scrollbar-overlay"
      },
      {
        "id": "scrollbar-both-axes",
        "title": "Both axes",
        "titleZh": "双向滚动",
        "note": "Vertical and horizontal scrollbars on a wide data table.",
        "noteZh": "宽数据表格上的垂直与水平滚动条。",
        "show": false,
        "demo": "scrollbar-both-axes"
      }
    ],
    "props": [
      {
        "name": "orientation",
        "type": "'vertical' | 'horizontal' | 'both'",
        "def": "'vertical'",
        "required": false,
        "desc": "Which axes render a scrollbar.",
        "descZh": "渲染滚动条的轴向。"
      },
      {
        "name": "overlay",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Overlays the thumb instead of reserving gutter space.",
        "descZh": "将滑块覆盖在内容上，而非预留滚动槽空间。"
      },
      {
        "name": "autoHide",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Fades the thumb out when idle and in on hover or scroll.",
        "descZh": "空闲时淡出滑块，悬停或滚动时淡入。"
      },
      {
        "name": "thickness",
        "type": "'sm' | 'md'",
        "def": "'md'",
        "required": false,
        "desc": "Thumb thickness for compact versus standard density.",
        "descZh": "滑块粗细，对应紧凑与标准密度。"
      },
      {
        "name": "className",
        "type": "string",
        "def": "undefined",
        "required": false,
        "desc": "Extra classes applied to the scroll container.",
        "descZh": "应用于滚动容器的附加类名。"
      }
    ],
    "changelog": [
      {
        "v": "1.4.1",
        "date": "2026-03-22",
        "notes": [
          "Fixed thumb flicker on momentum scroll in embedded HMI browsers."
        ],
        "notesZh": [
          "修复嵌入式 HMI 浏览器中惯性滚动时滑块闪烁的问题。"
        ]
      },
      {
        "v": "1.4.0",
        "date": "2026-01-15",
        "notes": [
          "Added auto-hide behavior with hover fade-in.",
          "Switched thumb fill to color.border.strong."
        ],
        "notesZh": [
          "新增自动隐藏行为及悬停淡入。",
          "滑块填充改用 color.border.strong。"
        ]
      }
    ],
    "repo": "packages/ui/src/Scrollbar.tsx",
    "version": "1.4.1",
    "lastEditBy": "m.okafor",
    "lastEditAt": "1 week ago",
    "lastCommit": "7d2e0b8",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "link",
    "name": "Link",
    "nameZh": "文字链接",
    "category": "Foundation",
    "categoryZh": "基础",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "link",
    "summary": "An inline text anchor for navigation, with built-in handling for internal and external destinations.",
    "summaryZh": "用于导航的内联文字锚点，内置内部与外部目标的处理。",
    "tags": [
      "navigation",
      "text",
      "interactive"
    ],
    "overview": "Link is the navigation counterpart to Button: use it for moving between pages, opening documents, or referencing external resources inline within body text. It inherits font size from surrounding copy and colors with accent.default, applying an underline on hover and an accent.focus ring on keyboard focus. External links automatically append an external icon and set rel='noopener noreferrer' for safety.",
    "overviewZh": "文字链接是按钮的导航对应物：用于页面间跳转、打开文档，或在正文中内联引用外部资源。它继承周围文本的字号，使用 accent.default 着色，悬停时显示下划线，键盘聚焦时应用 accent.focus 焦点环。外部链接会自动追加外部图标并设置 rel='noopener noreferrer' 以保证安全。",
    "dos": [
      "Use links for navigation and buttons for actions that change state.",
      "Write descriptive link text ('view run log') instead of 'click here'.",
      "Let external links surface the external icon so users know they leave the app."
    ],
    "dosZh": [
      "导航用链接，改变状态的操作用按钮。",
      "撰写描述性链接文案（'查看运行日志'），而非'点击这里'。",
      "让外部链接显示外部图标，使用户知晓将离开应用。"
    ],
    "donts": [
      "Don't style a link to look like a button to trigger an action.",
      "Don't open internal navigation in a new tab by default.",
      "Don't rely on color alone — keep the hover underline for accessibility."
    ],
    "dontsZh": [
      "不要把链接做成按钮样子去触发操作。",
      "不要默认在新标签页打开内部导航。",
      "不要仅依赖颜色——保留悬停下划线以满足无障碍。"
    ],
    "examples": [
      {
        "id": "link-inline",
        "title": "Inline link",
        "titleZh": "内联链接",
        "note": "A link embedded in a paragraph of body text.",
        "noteZh": "嵌入正文段落中的链接。",
        "show": true,
        "demo": "link-inline"
      },
      {
        "id": "link-external",
        "title": "External link",
        "titleZh": "外部链接",
        "note": "External destination with auto icon and safe rel attributes.",
        "noteZh": "外部目标，自动带图标与安全 rel 属性。",
        "show": true,
        "demo": "link-external"
      }
    ],
    "props": [
      {
        "name": "href",
        "type": "string",
        "def": "undefined",
        "required": true,
        "desc": "Destination URL or route path.",
        "descZh": "目标 URL 或路由路径。"
      },
      {
        "name": "external",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Marks the link as external; adds icon and safe rel.",
        "descZh": "标记为外部链接；添加图标与安全 rel 属性。"
      },
      {
        "name": "underline",
        "type": "'hover' | 'always' | 'none'",
        "def": "'hover'",
        "required": false,
        "desc": "When the underline appears.",
        "descZh": "下划线出现的时机。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Renders non-interactive muted text.",
        "descZh": "渲染为不可交互的置灰文本。"
      },
      {
        "name": "onClick",
        "type": "(e: MouseEvent) => void",
        "def": "undefined",
        "required": false,
        "desc": "Optional handler for client-side navigation.",
        "descZh": "用于客户端导航的可选回调。"
      }
    ],
    "changelog": [
      {
        "v": "2.0.0",
        "date": "2026-05-09",
        "notes": [
          "Auto-detect external hrefs and inject external icon.",
          "Underline now defaults to hover-only for cleaner body text."
        ],
        "notesZh": [
          "自动识别外部链接并注入外部图标。",
          "下划线默认改为仅悬停显示，使正文更整洁。"
        ]
      },
      {
        "v": "1.6.0",
        "date": "2026-02-20",
        "notes": [
          "Added disabled state and accent.focus keyboard ring."
        ],
        "notesZh": [
          "新增禁用状态及 accent.focus 键盘焦点环。"
        ]
      }
    ],
    "repo": "packages/ui/src/Link.tsx",
    "version": "2.0.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "5 days ago",
    "lastCommit": "c41b8af",
    "hasDraft": true,
    "wired": true
  },
  {
    "id": "tree",
    "name": "Tree",
    "nameZh": "树型结构",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "branch",
    "summary": "Hierarchical tree for navigating nested structures like equipment topologies, file systems, and recipe libraries.",
    "summaryZh": "用于浏览设备拓扑、文件系统、配方库等嵌套层级结构的树型组件。",
    "tags": [
      "navigation",
      "hierarchy",
      "expandable",
      "selectable"
    ],
    "overview": "Use Tree to expose deeply nested data such as a fab's tool/chamber hierarchy or a dataset folder structure. Indent each level by spacing.inset.md and render expand affordances with the chevronR/chevronD icons. Selected nodes use accent.default for the highlight and color.border.default for the connector guides; keep label rows on radius.control so hover states read cleanly.",
    "overviewZh": "使用 Tree 展示深层嵌套数据，例如晶圆厂的设备/腔室层级或数据集文件夹结构。每一层级以 spacing.inset.md 缩进，并使用 chevronR/chevronD 图标作为展开标识。选中节点使用 accent.default 高亮、color.border.default 绘制连接引导线；标签行保持 radius.control 圆角以使悬停态清晰可读。",
    "dos": [
      "Lazy-load child nodes on expand for large equipment topologies to keep first render fast.",
      "Pair the expand chevron with the whole row as a click target so dense trees stay easy to operate.",
      "Persist expanded/selected state so users return to the same context across sessions."
    ],
    "dosZh": [
      "对大型设备拓扑在展开时按需懒加载子节点，以保持首屏渲染快速。",
      "将展开箭头与整行一起作为点击目标，使密集的树型结构便于操作。",
      "持久化展开/选中状态，使用户跨会话回到相同的上下文。"
    ],
    "donts": [
      "Don't nest beyond five visible levels without a breadcrumb or search escape hatch.",
      "Don't auto-collapse sibling branches on selection; it disorients users mid-task.",
      "Don't use Tree for flat lists where a Menu or simple list is sufficient."
    ],
    "dontsZh": [
      "不要在没有面包屑或搜索退出机制的情况下嵌套超过五个可见层级。",
      "不要在选中时自动折叠兄弟分支，这会让用户在操作中迷失方向。",
      "扁平列表请勿使用 Tree，菜单或简单列表即可满足。"
    ],
    "examples": [
      {
        "id": "tree-basic",
        "title": "Basic equipment tree",
        "titleZh": "基础设备树",
        "note": "A three-level tool/module/chamber hierarchy with single selection.",
        "noteZh": "三层级的设备/模块/腔室层级结构，支持单选。",
        "show": true,
        "demo": "tree-basic"
      },
      {
        "id": "tree-checkable",
        "title": "Checkable tree with lazy load",
        "titleZh": "可勾选并懒加载的树",
        "note": "Multi-select with checkboxes; children fetched on expand.",
        "noteZh": "带复选框的多选；子节点在展开时获取。",
        "show": false,
        "demo": "tree-checkable"
      }
    ],
    "props": [
      {
        "name": "data",
        "type": "TreeNode[]",
        "def": "—",
        "required": true,
        "desc": "Array of root nodes; each node may carry children and metadata.",
        "descZh": "根节点数组；每个节点可携带子节点与元数据。"
      },
      {
        "name": "selectable",
        "type": "'single' | 'multiple' | false",
        "def": "'single'",
        "required": false,
        "desc": "Selection mode for node rows.",
        "descZh": "节点行的选择模式。"
      },
      {
        "name": "checkable",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Render checkboxes for bulk selection across the hierarchy.",
        "descZh": "渲染复选框以跨层级进行批量选择。"
      },
      {
        "name": "defaultExpandedKeys",
        "type": "string[]",
        "def": "[]",
        "required": false,
        "desc": "Keys of nodes expanded on initial mount.",
        "descZh": "初始挂载时展开的节点键。"
      },
      {
        "name": "loadChildren",
        "type": "(node: TreeNode) => Promise<TreeNode[]>",
        "def": "—",
        "required": false,
        "desc": "Async loader invoked when a node is expanded.",
        "descZh": "节点展开时调用的异步加载函数。"
      },
      {
        "name": "onSelect",
        "type": "(keys: string[]) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when the selected node set changes.",
        "descZh": "选中节点集合变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "2.4.0",
        "date": "2026-04-18",
        "notes": [
          "Added async loadChildren with skeleton placeholders.",
          "Improved keyboard arrow navigation across collapsed branches."
        ],
        "notesZh": [
          "新增带骨架占位的异步 loadChildren。",
          "改进了在折叠分支间的键盘方向键导航。"
        ]
      },
      {
        "v": "2.3.1",
        "date": "2026-02-09",
        "notes": [
          "Fixed connector line misalignment at deep indents."
        ],
        "notesZh": [
          "修复了深层缩进下连接线错位的问题。"
        ]
      }
    ],
    "repo": "packages/ui/src/Tree.tsx",
    "version": "2.4.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "3 days ago",
    "lastCommit": "a3f9c21",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "menu",
    "name": "Menu",
    "nameZh": "菜单",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": true,
    "cautionReason": "Anchors the primary navigation rail across every HMI and dashboard layout; structural or active-state changes ripple to all top-level routes and the four brand themes at once.",
    "cautionReasonZh": "承担所有 HMI 与仪表盘布局的主导航栏；其结构或激活态的改动会同时波及全部顶层路由与四种品牌主题，影响面广。",
    "icon": "route",
    "summary": "Vertical or inline menu for primary app navigation and grouped command lists.",
    "summaryZh": "用于应用主导航与分组命令列表的垂直或内联菜单。",
    "tags": [
      "navigation",
      "menu",
      "sidebar",
      "command"
    ],
    "overview": "Menu anchors the left rail of HMI and dashboard layouts, supporting groups, dividers, and collapsible submenus. The active item uses accent.default with a 2px indicator; item rows respect spacing.inset.md padding and radius.control on hover. Keep icons from the approved set aligned to the leading edge so scanning stays fast across the four brand themes.",
    "overviewZh": "Menu 支撑 HMI 与仪表盘布局的左侧导航栏，支持分组、分隔线与可折叠子菜单。激活项使用 accent.default 并带 2px 指示条；菜单行遵循 spacing.inset.md 内边距，悬停时呈现 radius.control 圆角。图标从批准集合中选取并左对齐，使其在四种品牌主题下都能快速扫读。",
    "dos": [
      "Group related destinations with headers and dividers to keep long rails scannable.",
      "Collapse the rail to icon-only on narrow viewports while preserving tooltips.",
      "Mark exactly one active item so users always know where they are."
    ],
    "dosZh": [
      "用标题与分隔线对相关目的地进行分组，使长导航栏易于扫读。",
      "在窄视口下将导航栏折叠为仅图标模式，同时保留工具提示。",
      "始终精确标记一个激活项，让用户清楚当前所在位置。"
    ],
    "donts": [
      "Don't mix navigation items with destructive actions in the same menu group.",
      "Don't nest submenus more than two levels deep in a sidebar context.",
      "Don't rely on color alone to convey the active state; pair with the indicator bar."
    ],
    "dontsZh": [
      "不要在同一菜单分组中混合导航项与破坏性操作。",
      "在侧边栏场景下子菜单嵌套不要超过两层。",
      "不要仅依赖颜色传达激活态；需配合指示条。"
    ],
    "examples": [
      {
        "id": "menu-sidebar",
        "title": "Sidebar navigation",
        "titleZh": "侧边栏导航",
        "note": "Grouped vertical menu with collapsible submenus and an active indicator.",
        "noteZh": "带可折叠子菜单与激活指示条的分组垂直菜单。",
        "show": true,
        "demo": "menu-sidebar"
      },
      {
        "id": "menu-inline",
        "title": "Inline command menu",
        "titleZh": "内联命令菜单",
        "note": "Flat menu used inside a popover for contextual commands.",
        "noteZh": "用于弹出层内的扁平菜单，承载上下文命令。",
        "show": false,
        "demo": "menu-inline"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "MenuItem[]",
        "def": "—",
        "required": true,
        "desc": "Menu entries, including groups, dividers, and submenus.",
        "descZh": "菜单条目，包含分组、分隔线与子菜单。"
      },
      {
        "name": "mode",
        "type": "'vertical' | 'inline' | 'horizontal'",
        "def": "'vertical'",
        "required": false,
        "desc": "Layout orientation of the menu.",
        "descZh": "菜单的布局方向。"
      },
      {
        "name": "selectedKey",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Key of the currently active item.",
        "descZh": "当前激活项的键。"
      },
      {
        "name": "collapsed",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Render the rail in icon-only collapsed state.",
        "descZh": "以仅图标的折叠状态渲染导航栏。"
      },
      {
        "name": "onSelect",
        "type": "(key: string) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when an item is activated.",
        "descZh": "菜单项被激活时触发。"
      }
    ],
    "changelog": [
      {
        "v": "3.1.0",
        "date": "2026-05-02",
        "notes": [
          "Added icon-only collapsed mode with tooltips.",
          "Active indicator now animates between items."
        ],
        "notesZh": [
          "新增带工具提示的仅图标折叠模式。",
          "激活指示条现在会在菜单项之间平滑过渡。"
        ]
      }
    ],
    "repo": "packages/ui/src/Menu.tsx",
    "version": "3.1.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "1 week ago",
    "lastCommit": "b71e4d8",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "tabs",
    "name": "Tabs",
    "nameZh": "页签",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "layers",
    "summary": "Tabbed interface for switching between peer views within the same screen.",
    "summaryZh": "用于在同一界面内切换同级视图的页签组件。",
    "tags": [
      "navigation",
      "tabs",
      "view-switch",
      "segmented"
    ],
    "overview": "Use Tabs to organize peer content such as Overview / Trends / Alarms on a tool dashboard. The active tab carries an accent.default underline or filled segment; inactive labels use color.text.muted with color.border.default separators. Keep tab counts under seven and let overflow scroll rather than wrap to preserve a single clean row.",
    "overviewZh": "使用 Tabs 组织同级内容，例如设备仪表盘上的 概览 / 趋势 / 告警。激活页签带 accent.default 下划线或填充段；非激活标签使用 color.text.muted，并以 color.border.default 分隔。页签数量保持在七个以内，溢出时滚动而非换行，以保持单行整洁。",
    "dos": [
      "Keep tab labels short and parallel so the bar reads as one scannable row.",
      "Preserve each tab's internal state when users switch back and forth.",
      "Use scrollable overflow for many tabs instead of wrapping onto two rows."
    ],
    "dosZh": [
      "保持页签标签简短且结构一致，使页签栏呈现为可扫读的一行。",
      "用户来回切换时保留各页签的内部状态。",
      "页签较多时使用可滚动溢出，而非换行到两行。"
    ],
    "donts": [
      "Don't use Tabs to step through a sequential flow; use a wizard or stepper instead.",
      "Don't hide critical actions inside a non-default tab without a clear cue.",
      "Don't change tab order dynamically; it breaks muscle memory."
    ],
    "dontsZh": [
      "不要用 Tabs 来走顺序流程；请改用向导或步骤条。",
      "不要在没有明确提示的情况下把关键操作藏在非默认页签里。",
      "不要动态改变页签顺序，这会破坏用户的肌肉记忆。"
    ],
    "examples": [
      {
        "id": "tabs-basic",
        "title": "Underline tabs",
        "titleZh": "下划线页签",
        "note": "Default underline style switching between three dashboard views.",
        "noteZh": "默认下划线样式，在三个仪表盘视图间切换。",
        "show": true,
        "demo": "tabs-basic"
      },
      {
        "id": "tabs-segmented",
        "title": "Segmented tabs",
        "titleZh": "分段页签",
        "note": "Pill-style segmented control for compact toolbars.",
        "noteZh": "胶囊式分段控件，适合紧凑工具栏。",
        "show": false,
        "demo": "tabs-segmented"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "TabItem[]",
        "def": "—",
        "required": true,
        "desc": "Tab definitions with key, label, and content.",
        "descZh": "页签定义，包含键、标签与内容。"
      },
      {
        "name": "activeKey",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Key of the currently selected tab (controlled).",
        "descZh": "当前选中页签的键（受控）。"
      },
      {
        "name": "variant",
        "type": "'underline' | 'segmented' | 'card'",
        "def": "'underline'",
        "required": false,
        "desc": "Visual style of the tab bar.",
        "descZh": "页签栏的视觉样式。"
      },
      {
        "name": "scrollable",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Allow horizontal scrolling when tabs overflow.",
        "descZh": "页签溢出时允许水平滚动。"
      },
      {
        "name": "onChange",
        "type": "(key: string) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when the active tab changes.",
        "descZh": "激活页签变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "2.2.0",
        "date": "2026-03-21",
        "notes": [
          "Added segmented variant.",
          "Overflow tabs now scroll with edge fade affordances."
        ],
        "notesZh": [
          "新增分段样式。",
          "溢出页签现在带边缘渐隐提示的滚动效果。"
        ]
      }
    ],
    "repo": "packages/ui/src/Tabs.tsx",
    "version": "2.2.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "5 days ago",
    "lastCommit": "c4d8e0a",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "filter",
    "name": "Filter",
    "nameZh": "过滤器",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "filter",
    "summary": "Composable filter bar for narrowing large datasets and event tables.",
    "summaryZh": "用于收窄大型数据集与事件表的可组合过滤栏。",
    "tags": [
      "navigation",
      "filter",
      "query",
      "facets"
    ],
    "overview": "Filter assembles facets, ranges, and search into one bar above data-analysis tables and alarm logs. Applied filters appear as removable tokens using radius.control and color.border.default; the active count badge uses accent.default. Keep the apply/reset actions pinned to the trailing edge and debounce text inputs so large queries don't thrash.",
    "overviewZh": "Filter 将分面、区间与搜索组合为数据分析表与告警日志上方的单一过滤栏。已应用的过滤条件以可移除的标签呈现，使用 radius.control 与 color.border.default；激活计数徽标使用 accent.default。将 应用/重置 操作固定在尾部，并对文本输入做防抖，避免大查询频繁抖动。",
    "dos": [
      "Show applied filters as removable tokens so users can see and undo them at a glance.",
      "Debounce free-text fields and defer expensive queries until apply where appropriate.",
      "Offer a single reset that clears every facet back to defaults."
    ],
    "dosZh": [
      "将已应用的过滤条件展示为可移除的标签，使用户一眼可见并可撤销。",
      "对自由文本字段做防抖，并在合适场景下延迟到点击应用时再执行昂贵查询。",
      "提供一键重置，将所有分面恢复为默认值。"
    ],
    "donts": [
      "Don't silently apply filters without reflecting them in the visible token row.",
      "Don't cram more than five primary facets inline; move the rest into a popover.",
      "Don't reset pagination state inconsistently when filters change."
    ],
    "dontsZh": [
      "不要在不反映到可见标签行的情况下静默应用过滤条件。",
      "不要在行内塞超过五个主要分面；其余移入弹出层。",
      "过滤条件变化时不要不一致地重置翻页状态。"
    ],
    "examples": [
      {
        "id": "filter-bar",
        "title": "Inline filter bar",
        "titleZh": "内联过滤栏",
        "note": "Search, facet selects, and a date range with removable tokens.",
        "noteZh": "搜索、分面选择与日期区间，配合可移除标签。",
        "show": true,
        "demo": "filter-bar"
      },
      {
        "id": "filter-popover",
        "title": "Advanced filter popover",
        "titleZh": "高级过滤弹出层",
        "note": "Overflow facets and boolean logic tucked into a popover panel.",
        "noteZh": "将溢出分面与布尔逻辑收纳进弹出面板。",
        "show": false,
        "demo": "filter-popover"
      }
    ],
    "props": [
      {
        "name": "facets",
        "type": "FacetDef[]",
        "def": "—",
        "required": true,
        "desc": "Definitions of available filter facets and their input types.",
        "descZh": "可用过滤分面及其输入类型的定义。"
      },
      {
        "name": "value",
        "type": "FilterState",
        "def": "{}",
        "required": false,
        "desc": "Current applied filter state (controlled).",
        "descZh": "当前已应用的过滤状态（受控）。"
      },
      {
        "name": "applyMode",
        "type": "'instant' | 'manual'",
        "def": "'instant'",
        "required": false,
        "desc": "Whether changes apply immediately or on an explicit apply action.",
        "descZh": "更改是立即应用还是在显式点击应用时生效。"
      },
      {
        "name": "showReset",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Render a reset-all control.",
        "descZh": "渲染全部重置控件。"
      },
      {
        "name": "onChange",
        "type": "(state: FilterState) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when the filter state changes.",
        "descZh": "过滤状态变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "1.9.0",
        "date": "2026-04-30",
        "notes": [
          "Added manual apply mode with a pending-changes badge.",
          "Token row now supports keyboard removal."
        ],
        "notesZh": [
          "新增带待应用更改徽标的手动应用模式。",
          "标签行现在支持键盘移除。"
        ]
      }
    ],
    "repo": "packages/ui/src/Filter.tsx",
    "version": "1.9.0",
    "lastEditBy": "m.okafor",
    "lastEditAt": "2 days ago",
    "lastCommit": "d92a16f",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "pagination",
    "name": "Pagination",
    "nameZh": "翻页器",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chevronR",
    "summary": "Page navigator for splitting long tables and result lists into pages.",
    "summaryZh": "用于将长表格与结果列表分页浏览的翻页组件。",
    "tags": [
      "navigation",
      "pagination",
      "table",
      "paging"
    ],
    "overview": "Pagination sits below data tables and search results to move through large record sets without infinite scroll. The current page uses accent.default; sibling pages and ellipses use color.text.muted on radius.control targets. Include a page-size selector and a total count so operators can gauge dataset scale at a glance.",
    "overviewZh": "Pagination 位于数据表与搜索结果下方，无需无限滚动即可浏览大型记录集。当前页使用 accent.default；相邻页码与省略号使用 color.text.muted，作用于 radius.control 的点击目标。提供每页条数选择器与总数，使操作员可一眼判断数据集规模。",
    "dos": [
      "Show the total count and current range so users understand dataset size.",
      "Offer a page-size selector for tables that vary widely in row count.",
      "Keep the control sticky at the table footer for long pages."
    ],
    "dosZh": [
      "显示总数与当前范围，使用户了解数据集规模。",
      "为行数差异较大的表格提供每页条数选择器。",
      "在长页面中将控件吸附在表格底部。"
    ],
    "donts": [
      "Don't combine Pagination with infinite scroll on the same list.",
      "Don't render every page number for very large sets; use ellipses.",
      "Don't reset the user to page one on unrelated state changes."
    ],
    "dontsZh": [
      "不要在同一列表上同时使用翻页器与无限滚动。",
      "数据集很大时不要渲染全部页码；使用省略号。",
      "不要在无关的状态变化时把用户重置回第一页。"
    ],
    "examples": [
      {
        "id": "pagination-basic",
        "title": "Standard pagination",
        "titleZh": "标准翻页",
        "note": "Page numbers with prev/next and a page-size selector.",
        "noteZh": "带上一页/下一页与每页条数选择器的页码。",
        "show": true,
        "demo": "pagination-basic"
      },
      {
        "id": "pagination-simple",
        "title": "Simple pager",
        "titleZh": "简洁翻页",
        "note": "Compact prev/next only for narrow toolbars.",
        "noteZh": "仅上一页/下一页的紧凑形态，适合窄工具栏。",
        "show": false,
        "demo": "pagination-simple"
      }
    ],
    "props": [
      {
        "name": "total",
        "type": "number",
        "def": "—",
        "required": true,
        "desc": "Total number of records across all pages.",
        "descZh": "所有页的记录总数。"
      },
      {
        "name": "current",
        "type": "number",
        "def": "1",
        "required": false,
        "desc": "Currently active page index (1-based).",
        "descZh": "当前激活的页码（从 1 开始）。"
      },
      {
        "name": "pageSize",
        "type": "number",
        "def": "20",
        "required": false,
        "desc": "Number of records shown per page.",
        "descZh": "每页显示的记录数。"
      },
      {
        "name": "showSizeChanger",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Render the page-size selector.",
        "descZh": "渲染每页条数选择器。"
      },
      {
        "name": "onChange",
        "type": "(page: number, size: number) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when page or page size changes.",
        "descZh": "页码或每页条数变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "1.6.0",
        "date": "2026-02-27",
        "notes": [
          "Added simple pager variant.",
          "Page-size selector now syncs with URL query params."
        ],
        "notesZh": [
          "新增简洁翻页样式。",
          "每页条数选择器现在与 URL 查询参数同步。"
        ]
      }
    ],
    "repo": "packages/ui/src/Pagination.tsx",
    "version": "1.6.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "2 weeks ago",
    "lastCommit": "e0b7c33",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "dropdown",
    "name": "Dropdown",
    "nameZh": "下拉菜单",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chevronD",
    "summary": "Triggered overlay menu for contextual actions and compact option lists.",
    "summaryZh": "由触发器弹出的浮层菜单，用于上下文操作与紧凑选项列表。",
    "tags": [
      "navigation",
      "dropdown",
      "overlay",
      "menu"
    ],
    "overview": "Dropdown reveals a floating menu from a button or icon trigger for actions like row operations or view options. The panel sits on the elevated surface with radius.control corners and color.border.default edges; items highlight with accent.default on hover. Always pin placement to the trigger and trap focus so keyboard users can traverse and dismiss cleanly.",
    "overviewZh": "Dropdown 由按钮或图标触发器弹出浮动菜单，用于行操作或视图选项等动作。面板位于抬升表面，带 radius.control 圆角与 color.border.default 边缘；菜单项悬停时以 accent.default 高亮。始终将位置锚定到触发器并进行焦点捕获，使键盘用户可顺畅遍历与关闭。",
    "dos": [
      "Anchor the panel to its trigger and flip placement to stay within the viewport.",
      "Trap and restore focus so keyboard and screen-reader users can navigate the menu.",
      "Keep menus short; group with dividers when actions span categories."
    ],
    "dosZh": [
      "将面板锚定到触发器，并在超出视口时翻转位置。",
      "进行焦点捕获与恢复，使键盘与读屏用户可导航菜单。",
      "保持菜单简短；操作跨类别时用分隔线分组。"
    ],
    "donts": [
      "Don't use Dropdown for selecting a value from many options; use a Select.",
      "Don't nest dropdowns more than one level deep.",
      "Don't leave the panel open when the trigger scrolls out of view."
    ],
    "dontsZh": [
      "不要用 Dropdown 从大量选项中选取值；请使用 Select。",
      "下拉菜单嵌套不要超过一层。",
      "触发器滚出视野时不要让面板保持打开。"
    ],
    "examples": [
      {
        "id": "dropdown-actions",
        "title": "Action dropdown",
        "titleZh": "操作下拉菜单",
        "note": "More-menu trigger revealing row actions with a divider.",
        "noteZh": "更多菜单触发器，弹出带分隔线的行操作。",
        "show": true,
        "demo": "dropdown-actions"
      }
    ],
    "props": [
      {
        "name": "trigger",
        "type": "ReactNode",
        "def": "—",
        "required": true,
        "desc": "Element that opens the dropdown when activated.",
        "descZh": "激活时打开下拉菜单的元素。"
      },
      {
        "name": "items",
        "type": "DropdownItem[]",
        "def": "—",
        "required": true,
        "desc": "Menu entries, dividers, and disabled states.",
        "descZh": "菜单条目、分隔线与禁用状态。"
      },
      {
        "name": "placement",
        "type": "'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'",
        "def": "'bottom-start'",
        "required": false,
        "desc": "Preferred panel position relative to the trigger.",
        "descZh": "面板相对触发器的首选位置。"
      },
      {
        "name": "triggerOn",
        "type": "'click' | 'hover'",
        "def": "'click'",
        "required": false,
        "desc": "Interaction that opens the panel.",
        "descZh": "打开面板的交互方式。"
      },
      {
        "name": "onSelect",
        "type": "(key: string) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when an item is chosen.",
        "descZh": "选中条目时触发。"
      }
    ],
    "changelog": [
      {
        "v": "2.0.1",
        "date": "2026-03-12",
        "notes": [
          "Fixed focus restoration after dismissal.",
          "Improved viewport-edge flipping logic."
        ],
        "notesZh": [
          "修复了关闭后的焦点恢复。",
          "改进了视口边缘翻转逻辑。"
        ]
      }
    ],
    "repo": "packages/ui/src/Dropdown.tsx",
    "version": "2.0.1",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "4 days ago",
    "lastCommit": "f51a8b9",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "anchor",
    "name": "Anchor",
    "nameZh": "锚点",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "beta",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "link",
    "summary": "In-page anchor navigation that tracks scroll position across long documents.",
    "summaryZh": "页内锚点导航，可在长文档中跟踪滚动位置。",
    "tags": [
      "navigation",
      "anchor",
      "scrollspy",
      "in-page"
    ],
    "overview": "Anchor builds a sticky table of contents for long settings pages and configuration docs, highlighting the section in view. The active link uses accent.default with an indicator rail on color.border.default; links sit on radius.control hover targets. Use smooth scrolling with an offset so sticky headers never hide the target heading.",
    "overviewZh": "Anchor 为长设置页与配置文档构建吸附式目录，并高亮当前可见的章节。激活链接使用 accent.default，配合基于 color.border.default 的指示轨；链接位于 radius.control 的悬停目标上。使用带偏移的平滑滚动，避免吸顶头部遮挡目标标题。",
    "dos": [
      "Set a scroll offset equal to any sticky header so targets land fully in view.",
      "Sync the active link with scroll position via an intersection observer.",
      "Keep the anchor list to one or two levels for clarity."
    ],
    "dosZh": [
      "将滚动偏移设置为吸顶头部的高度，使目标完整落入视野。",
      "通过交叉观察器使激活链接与滚动位置同步。",
      "锚点列表保持一到两级以确保清晰。"
    ],
    "donts": [
      "Don't use Anchor for navigating between separate pages; use Menu or Breadcrumb.",
      "Don't list every minor heading; surface only meaningful sections.",
      "Don't animate scroll so slowly that it feels sluggish on long jumps."
    ],
    "dontsZh": [
      "不要用 Anchor 在不同页面间导航；请使用菜单或面包屑。",
      "不要列出每个次要标题；只呈现有意义的章节。",
      "不要把滚动动画做得太慢，长距离跳转时会显得迟钝。"
    ],
    "examples": [
      {
        "id": "anchor-toc",
        "title": "Sticky table of contents",
        "titleZh": "吸附式目录",
        "note": "Scrollspy anchor list with an active indicator rail.",
        "noteZh": "带激活指示轨的滚动监听锚点列表。",
        "show": true,
        "demo": "anchor-toc"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "AnchorLink[]",
        "def": "—",
        "required": true,
        "desc": "Anchor links pointing to in-page target ids.",
        "descZh": "指向页内目标 id 的锚点链接。"
      },
      {
        "name": "offsetTop",
        "type": "number",
        "def": "0",
        "required": false,
        "desc": "Scroll offset to clear sticky headers.",
        "descZh": "用于避开吸顶头部的滚动偏移。"
      },
      {
        "name": "bounds",
        "type": "number",
        "def": "5",
        "required": false,
        "desc": "Activation bounds in pixels around a target.",
        "descZh": "目标周围的激活边界（像素）。"
      },
      {
        "name": "onChange",
        "type": "(activeId: string) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when the active anchor changes on scroll.",
        "descZh": "滚动导致激活锚点变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "0.8.0",
        "date": "2026-05-19",
        "notes": [
          "Initial beta release with intersection-observer scrollspy.",
          "Added configurable offsetTop for sticky layouts."
        ],
        "notesZh": [
          "首个 Beta 版本，基于交叉观察器实现滚动监听。",
          "新增可配置的 offsetTop 以适配吸顶布局。"
        ]
      }
    ],
    "repo": "packages/ui/src/Anchor.tsx",
    "version": "0.8.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "6 days ago",
    "lastCommit": "1c2d3e4",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "tag",
    "name": "Tag",
    "nameZh": "标签",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "tag",
    "summary": "Compact label for categorizing, filtering, and marking status or attributes.",
    "summaryZh": "用于分类、过滤以及标记状态或属性的紧凑标签。",
    "tags": [
      "navigation",
      "tag",
      "label",
      "chip"
    ],
    "overview": "Tag marks records with categories, statuses, or selectable filter chips across tables and cards. Use semantic color roles for meaning and color.border.default for neutral outlines, all on radius.control corners. Keep tag text to one or two words and make removable tags expose a clear close affordance with the close icon.",
    "overviewZh": "Tag 用于在表格与卡片中标记记录的类别、状态或可选过滤芯片。用语义颜色角色表达含义、color.border.default 表达中性描边，全部采用 radius.control 圆角。标签文本保持一到两个词，可移除标签需用 close 图标暴露清晰的关闭标识。",
    "dos": [
      "Map tag colors to consistent semantic meanings across products.",
      "Provide a close affordance for tags users can remove.",
      "Keep labels short so tag rows stay compact and scannable."
    ],
    "dosZh": [
      "在各产品间将标签颜色映射到一致的语义含义。",
      "为用户可移除的标签提供关闭标识。",
      "保持标签文本简短，使标签行紧凑且易扫读。"
    ],
    "donts": [
      "Don't use too many colors at once; it dilutes their meaning.",
      "Don't pack long sentences into a tag; use text instead.",
      "Don't make non-interactive tags look clickable."
    ],
    "dontsZh": [
      "不要一次使用过多颜色，这会稀释其含义。",
      "不要把长句塞进标签；请改用正文文本。",
      "不要让非交互标签看起来可点击。"
    ],
    "examples": [
      {
        "id": "tag-status",
        "title": "Status tags",
        "titleZh": "状态标签",
        "note": "Semantic-colored tags for running, idle, and fault states.",
        "noteZh": "语义着色标签，表示运行、空闲与故障状态。",
        "show": true,
        "demo": "tag-status"
      },
      {
        "id": "tag-removable",
        "title": "Removable filter tags",
        "titleZh": "可移除过滤标签",
        "note": "Closable chips reflecting applied filters.",
        "noteZh": "可关闭芯片，反映已应用的过滤条件。",
        "show": false,
        "demo": "tag-removable"
      }
    ],
    "props": [
      {
        "name": "children",
        "type": "ReactNode",
        "def": "—",
        "required": true,
        "desc": "Tag label content.",
        "descZh": "标签的文本内容。"
      },
      {
        "name": "color",
        "type": "'neutral' | 'success' | 'warning' | 'danger' | 'info'",
        "def": "'neutral'",
        "required": false,
        "desc": "Semantic color role of the tag.",
        "descZh": "标签的语义颜色角色。"
      },
      {
        "name": "closable",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Render a close affordance to remove the tag.",
        "descZh": "渲染关闭标识以移除标签。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md'",
        "def": "'md'",
        "required": false,
        "desc": "Tag sizing scale.",
        "descZh": "标签尺寸档位。"
      },
      {
        "name": "onClose",
        "type": "() => void",
        "def": "—",
        "required": false,
        "desc": "Fires when a closable tag is dismissed.",
        "descZh": "可关闭标签被移除时触发。"
      }
    ],
    "changelog": [
      {
        "v": "1.4.0",
        "date": "2026-04-08",
        "notes": [
          "Added sm size for dense tables.",
          "Aligned semantic colors with the latest token set."
        ],
        "notesZh": [
          "新增适合密集表格的 sm 尺寸。",
          "将语义颜色与最新令牌集对齐。"
        ]
      }
    ],
    "repo": "packages/ui/src/Tag.tsx",
    "version": "1.4.0",
    "lastEditBy": "m.okafor",
    "lastEditAt": "1 week ago",
    "lastCommit": "2b6f0d1",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "breadcrumb",
    "name": "Breadcrumb",
    "nameZh": "面包屑",
    "category": "Navigation",
    "categoryZh": "导航",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chevronR",
    "summary": "Trail of links showing the user's location within a nested hierarchy.",
    "summaryZh": "显示用户在嵌套层级中所处位置的链接路径。",
    "tags": [
      "navigation",
      "breadcrumb",
      "hierarchy",
      "wayfinding"
    ],
    "overview": "Breadcrumb gives wayfinding for deep routes like Fleet / Tool / Chamber / Recipe so users can jump back up the tree. Ancestor links use color.text.muted while the current page reads in default text; separators are the chevronR icon on color.border.default. Collapse the middle into an overflow menu when the trail exceeds the available width.",
    "overviewZh": "Breadcrumb 为深层路由（如 设备群 / 设备 / 腔室 / 配方）提供路径指引，使用户可逐级回溯。祖先链接使用 color.text.muted，当前页以默认文本呈现；分隔符为 chevronR 图标，作用于 color.border.default。当路径超出可用宽度时，将中间部分折叠为溢出菜单。",
    "dos": [
      "Make every ancestor segment a working link back up the hierarchy.",
      "Collapse the middle into an overflow menu when space is tight.",
      "Render the current page as plain text, not a link."
    ],
    "dosZh": [
      "让每个祖先节点都成为可回溯层级的有效链接。",
      "空间紧张时将中间部分折叠为溢出菜单。",
      "当前页以纯文本呈现，而非链接。"
    ],
    "donts": [
      "Don't use Breadcrumb as primary navigation; it is a secondary aid.",
      "Don't include the current page as a clickable link.",
      "Don't let a long trail wrap onto multiple lines."
    ],
    "dontsZh": [
      "不要把面包屑当作主导航；它是辅助手段。",
      "不要把当前页做成可点击链接。",
      "不要让过长的路径换行到多行。"
    ],
    "examples": [
      {
        "id": "breadcrumb-basic",
        "title": "Basic breadcrumb",
        "titleZh": "基础面包屑",
        "note": "Four-level trail with chevron separators.",
        "noteZh": "四级路径，使用箭头分隔符。",
        "show": true,
        "demo": "breadcrumb-basic"
      },
      {
        "id": "breadcrumb-overflow",
        "title": "Collapsed breadcrumb",
        "titleZh": "折叠面包屑",
        "note": "Long trail with a middle overflow menu.",
        "noteZh": "中间带溢出菜单的长路径。",
        "show": false,
        "demo": "breadcrumb-overflow"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "BreadcrumbItem[]",
        "def": "—",
        "required": true,
        "desc": "Ordered path segments from root to current page.",
        "descZh": "从根节点到当前页的有序路径节点。"
      },
      {
        "name": "separator",
        "type": "ReactNode",
        "def": "'chevronR'",
        "required": false,
        "desc": "Custom separator rendered between segments.",
        "descZh": "节点之间渲染的自定义分隔符。"
      },
      {
        "name": "maxItems",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Collapse the middle into an overflow menu beyond this count.",
        "descZh": "超过该数量时将中间部分折叠为溢出菜单。"
      },
      {
        "name": "onNavigate",
        "type": "(href: string) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when an ancestor segment is activated.",
        "descZh": "激活某个祖先节点时触发。"
      }
    ],
    "changelog": [
      {
        "v": "1.3.0",
        "date": "2026-03-04",
        "notes": [
          "Added maxItems overflow collapsing.",
          "Separators now inherit color.border.default."
        ],
        "notesZh": [
          "新增 maxItems 溢出折叠。",
          "分隔符现在继承 color.border.default。"
        ]
      }
    ],
    "repo": "packages/ui/src/Breadcrumb.tsx",
    "version": "1.3.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "9 days ago",
    "lastCommit": "3a7c5e2",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "input",
    "name": "Input",
    "nameZh": "输入框",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": true,
    "cautionReason": "The base text field underpins nearly every form across all 4 product lines; size, border, and focus-ring changes ripple to Search, Select, NumberInput and DatePicker, which compose it. Coordinate with each team before merging.",
    "cautionReasonZh": "作为基础文本字段，它支撑着全部 4 条产品线中几乎所有表单；尺寸、边框与聚焦环的改动会波及由其组合而成的 Search、Select、NumberInput 与 DatePicker。合并前请与各团队协调。",
    "icon": "edit",
    "summary": "Single-line text field for free-form data entry, the foundation of every SiCARRIER UI form.",
    "summaryZh": "用于自由输入文本的单行字段，是 SiCARRIER UI 所有表单的基础。",
    "tags": [
      "form",
      "text",
      "field"
    ],
    "overview": "Input is the canonical text field that every other entry control composes. Its border draws from color.border.default and switches to accent.default on focus, with the focus ring offset for clarity on both light and dark surfaces. Always pair it with a visible label and keep inset padding at spacing.inset.md.",
    "overviewZh": "Input 是所有其他录入控件赖以组合的标准文本字段。其边框取自 color.border.default，聚焦时切换为 accent.default，并对聚焦环做偏移处理，以便在浅色与深色表面上都清晰可辨。请始终为其搭配可见标签，并将内边距保持在 spacing.inset.md。",
    "dos": [
      "Pair every input with a visible, persistent label.",
      "Use placeholder text for format hints, not as a label.",
      "Surface validation errors inline beneath the field."
    ],
    "dosZh": [
      "为每个输入框搭配可见且常驻的标签。",
      "占位文本用于提示格式，而非充当标签。",
      "在字段下方就地呈现校验错误。"
    ],
    "donts": [
      "Rely on placeholder text alone to label a field.",
      "Disable an input without explaining why nearby.",
      "Use a single-line input for long multi-line content."
    ],
    "dontsZh": [
      "仅靠占位文本来标注字段。",
      "禁用输入框却不在旁边说明原因。",
      "用单行输入框承载多行长文本。"
    ],
    "examples": [
      {
        "id": "input-basic",
        "title": "Basic input",
        "titleZh": "基础输入框",
        "note": "Label, field, and helper text in one stack.",
        "noteZh": "标签、字段与辅助文本组成一组。",
        "show": true,
        "demo": "input-basic"
      },
      {
        "id": "input-states",
        "title": "States",
        "titleZh": "状态",
        "note": "Default, focus, error and disabled from border tokens.",
        "noteZh": "默认、聚焦、错误与禁用状态取自边框令牌。",
        "show": true,
        "demo": "input-states"
      },
      {
        "id": "input-addon",
        "title": "With addon",
        "titleZh": "带附加内容",
        "note": "Leading icon or trailing unit slot.",
        "noteZh": "前置图标或后置单位槽位。",
        "show": false,
        "demo": "input-addon"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Current field value.",
        "descZh": "字段当前值。"
      },
      {
        "name": "onChange",
        "type": "(e: ChangeEvent) => void",
        "def": "—",
        "required": true,
        "desc": "Change handler.",
        "descZh": "变更处理函数。"
      },
      {
        "name": "placeholder",
        "type": "string",
        "def": "''",
        "required": false,
        "desc": "Format hint shown when empty.",
        "descZh": "为空时显示的格式提示。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg'",
        "def": "'md'",
        "required": false,
        "desc": "Control height.",
        "descZh": "控件高度。"
      },
      {
        "name": "error",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Renders the error border and ring.",
        "descZh": "呈现错误边框与聚焦环。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Prevents interaction.",
        "descZh": "阻止交互。"
      }
    ],
    "changelog": [
      {
        "v": "2.6.0",
        "date": "2026-05-30",
        "notes": [
          "Focus ring now references `accent.default` with a 2px offset.",
          "Added `lg` size."
        ],
        "notesZh": [
          "聚焦环现引用 `accent.default` 并带 2px 偏移。",
          "新增 `lg` 尺寸。"
        ]
      },
      {
        "v": "2.5.0",
        "date": "2026-04-12",
        "notes": [
          "Error state border references `color.border.danger`."
        ],
        "notesZh": [
          "错误状态边框引用 `color.border.danger`。"
        ]
      }
    ],
    "repo": "packages/ui/src/Input.tsx",
    "version": "2.6.0",
    "lastEditBy": "m.okafor",
    "lastEditAt": "2 days ago",
    "lastCommit": "b7e1d04",
    "hasDraft": true,
    "wired": true
  },
  {
    "id": "numberinput",
    "name": "NumberInput",
    "nameZh": "数字输入框",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "hash",
    "summary": "Numeric field with steppers, min/max clamping and unit suffix for measured values.",
    "summaryZh": "带步进器、最小/最大值钳制与单位后缀的数字字段，用于录入测量值。",
    "tags": [
      "form",
      "number",
      "stepper"
    ],
    "overview": "NumberInput extends Input for bounded numeric entry on HMI setpoint and analytics forms. Stepper buttons share the control height scale and clamp to min/max, while the unit suffix sits in a muted color.text.muted slot. Right-align the value so digits line up in dense parameter tables.",
    "overviewZh": "NumberInput 在 Input 基础上扩展，用于 HMI 设定值与分析表单中的有界数字录入。步进按钮沿用控件高度比例并按最小/最大值钳制，单位后缀置于柔和的 color.text.muted 槽位中。请将数值右对齐，使数字在密集的参数表中对齐。",
    "dos": [
      "Set sensible min, max and step for the measured quantity.",
      "Show the unit so the operator never guesses.",
      "Right-align values in parameter tables."
    ],
    "dosZh": [
      "为所测量值设定合理的最小值、最大值与步长。",
      "显示单位，让操作员无需猜测。",
      "在参数表中将数值右对齐。"
    ],
    "donts": [
      "Allow free text where only numbers are valid.",
      "Hide clamping silently — signal when a value is capped.",
      "Use steppers for ranges too large to click through."
    ],
    "dontsZh": [
      "在仅允许数字处放任自由文本输入。",
      "静默钳制——当值被限制时应给出提示。",
      "对过大、无法逐次点击的范围使用步进器。"
    ],
    "examples": [
      {
        "id": "numberinput-basic",
        "title": "Basic",
        "titleZh": "基础",
        "note": "Steppers with min/max clamp.",
        "noteZh": "带最小/最大值钳制的步进器。",
        "show": true,
        "demo": "numberinput-basic"
      },
      {
        "id": "numberinput-unit",
        "title": "With unit",
        "titleZh": "带单位",
        "note": "Unit suffix in `color.text.muted`.",
        "noteZh": "单位后缀采用 `color.text.muted`。",
        "show": true,
        "demo": "numberinput-unit"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "number",
        "def": "—",
        "required": true,
        "desc": "Current numeric value.",
        "descZh": "当前数值。"
      },
      {
        "name": "onChange",
        "type": "(v: number) => void",
        "def": "—",
        "required": true,
        "desc": "Change handler.",
        "descZh": "变更处理函数。"
      },
      {
        "name": "min",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Lower clamp bound.",
        "descZh": "下限钳制值。"
      },
      {
        "name": "max",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Upper clamp bound.",
        "descZh": "上限钳制值。"
      },
      {
        "name": "step",
        "type": "number",
        "def": "1",
        "required": false,
        "desc": "Stepper increment.",
        "descZh": "步进增量。"
      },
      {
        "name": "unit",
        "type": "string",
        "def": "''",
        "required": false,
        "desc": "Suffix shown after the value.",
        "descZh": "数值后显示的单位后缀。"
      }
    ],
    "changelog": [
      {
        "v": "1.7.1",
        "date": "2026-05-19",
        "notes": [
          "Clamping now flashes the field briefly when a value is capped.",
          "Unit suffix references `color.text.muted`."
        ],
        "notesZh": [
          "当值被限制时字段会短暂闪烁提示。",
          "单位后缀引用 `color.text.muted`。"
        ]
      },
      {
        "v": "1.7.0",
        "date": "2026-04-05",
        "notes": [
          "Added `step` precision handling for decimals."
        ],
        "notesZh": [
          "新增针对小数的 `step` 精度处理。"
        ]
      }
    ],
    "repo": "packages/ui/src/NumberInput.tsx",
    "version": "1.7.1",
    "lastEditBy": "p.narang",
    "lastEditAt": "4 days ago",
    "lastCommit": "c9a4e22",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "search",
    "name": "Search",
    "nameZh": "搜索",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "search",
    "summary": "Search field with leading icon, clear affordance and optional inline suggestions.",
    "summaryZh": "带前置图标、清除操作与可选内联建议的搜索字段。",
    "tags": [
      "form",
      "search",
      "filter"
    ],
    "overview": "Search is a specialized Input for querying lists, tables and command palettes. The leading search icon and trailing clear button use color.text.muted, and results should be debounced so the dropdown does not flicker on every keystroke. Reach for it whenever a dataset is large enough that scanning is impractical.",
    "overviewZh": "Search 是用于检索列表、表格与命令面板的专用 Input。前置搜索图标与后置清除按钮采用 color.text.muted，结果应做防抖处理，避免下拉框在每次按键时闪烁。当数据集大到难以逐项浏览时即可使用它。",
    "dos": [
      "Debounce queries to avoid result flicker.",
      "Offer a one-click clear affordance.",
      "Show an empty-state message when nothing matches."
    ],
    "dosZh": [
      "对查询做防抖处理，避免结果闪烁。",
      "提供一键清除的操作入口。",
      "无匹配项时显示空状态提示。"
    ],
    "donts": [
      "Trigger a network request on every keystroke.",
      "Hide the search icon affordance.",
      "Use Search where a simple filter Select suffices."
    ],
    "dontsZh": [
      "每次按键都触发网络请求。",
      "隐藏搜索图标这一可视提示。",
      "在简单筛选下拉即可满足处使用 Search。"
    ],
    "examples": [
      {
        "id": "search-basic",
        "title": "Basic search",
        "titleZh": "基础搜索",
        "note": "Leading icon plus clear button.",
        "noteZh": "前置图标加清除按钮。",
        "show": true,
        "demo": "search-basic"
      },
      {
        "id": "search-suggest",
        "title": "With suggestions",
        "titleZh": "带建议",
        "note": "Debounced inline result dropdown.",
        "noteZh": "防抖的内联结果下拉。",
        "show": true,
        "demo": "search-suggest"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Current query string.",
        "descZh": "当前查询字符串。"
      },
      {
        "name": "onChange",
        "type": "(q: string) => void",
        "def": "—",
        "required": true,
        "desc": "Query change handler.",
        "descZh": "查询变更处理函数。"
      },
      {
        "name": "placeholder",
        "type": "string",
        "def": "'Search'",
        "required": false,
        "desc": "Field hint text.",
        "descZh": "字段提示文本。"
      },
      {
        "name": "suggestions",
        "type": "Suggestion[]",
        "def": "—",
        "required": false,
        "desc": "Inline result items.",
        "descZh": "内联结果项。"
      },
      {
        "name": "loading",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Shows the in-field spinner.",
        "descZh": "显示字段内加载指示。"
      }
    ],
    "changelog": [
      {
        "v": "1.5.0",
        "date": "2026-05-22",
        "notes": [
          "Added inline `suggestions` dropdown.",
          "Clear button now references `color.text.muted`."
        ],
        "notesZh": [
          "新增内联 `suggestions` 下拉。",
          "清除按钮现引用 `color.text.muted`。"
        ]
      },
      {
        "v": "1.4.0",
        "date": "2026-03-28",
        "notes": [
          "Added built-in debounce."
        ],
        "notesZh": [
          "新增内置防抖。"
        ]
      }
    ],
    "repo": "packages/ui/src/Search.tsx",
    "version": "1.5.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "6 days ago",
    "lastCommit": "d3f8a17",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "select",
    "name": "Select",
    "nameZh": "下拉选择器",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chevronD",
    "summary": "Dropdown for choosing one or many values from a known list of options.",
    "summaryZh": "用于从已知选项列表中选择单个或多个值的下拉控件。",
    "tags": [
      "form",
      "dropdown",
      "choice"
    ],
    "overview": "Select presents a constrained set of choices in a popover anchored to a trigger that mirrors the Input border. The chevron rotates on open and the active option draws from accent.default. Use it for 5 or more options; for fewer, Radio keeps every choice visible.",
    "overviewZh": "Select 在锚定于触发器的浮层中呈现一组受限选项，触发器边框与 Input 保持一致。展开时箭头旋转，当前选项取自 accent.default。选项达 5 个及以上时使用它；少于此数时，Radio 能让所有选项保持可见。",
    "dos": [
      "Use Select when there are five or more options.",
      "Make options searchable once the list grows long.",
      "Show the selected value clearly in the trigger."
    ],
    "dosZh": [
      "选项达 5 个及以上时使用 Select。",
      "列表变长后让选项可被搜索。",
      "在触发器中清晰显示已选值。"
    ],
    "donts": [
      "Use Select for two or three options — use Radio.",
      "Nest a Select inside a tightly scrolling region.",
      "Leave multi-select state ambiguous."
    ],
    "dontsZh": [
      "对两三个选项使用 Select——应改用 Radio。",
      "将 Select 嵌入紧凑滚动区域内。",
      "让多选状态含糊不清。"
    ],
    "examples": [
      {
        "id": "select-basic",
        "title": "Single select",
        "titleZh": "单选",
        "note": "Trigger mirrors the Input border.",
        "noteZh": "触发器边框与 Input 一致。",
        "show": true,
        "demo": "select-basic"
      },
      {
        "id": "select-multi",
        "title": "Multi-select",
        "titleZh": "多选",
        "note": "Checked options use `accent.default`.",
        "noteZh": "选中项采用 `accent.default`。",
        "show": true,
        "demo": "select-multi"
      },
      {
        "id": "select-search",
        "title": "Searchable",
        "titleZh": "可搜索",
        "note": "Filter field for long option lists.",
        "noteZh": "为长选项列表提供筛选字段。",
        "show": false,
        "demo": "select-search"
      }
    ],
    "props": [
      {
        "name": "options",
        "type": "Option[]",
        "def": "—",
        "required": true,
        "desc": "Selectable items.",
        "descZh": "可选项。"
      },
      {
        "name": "value",
        "type": "string | string[]",
        "def": "—",
        "required": true,
        "desc": "Selected value(s).",
        "descZh": "已选值。"
      },
      {
        "name": "onChange",
        "type": "(v: string | string[]) => void",
        "def": "—",
        "required": true,
        "desc": "Selection handler.",
        "descZh": "选择处理函数。"
      },
      {
        "name": "multiple",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Allow selecting many.",
        "descZh": "允许多选。"
      },
      {
        "name": "searchable",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Adds a filter field.",
        "descZh": "添加筛选字段。"
      },
      {
        "name": "placeholder",
        "type": "string",
        "def": "'Select'",
        "required": false,
        "desc": "Empty-state trigger text.",
        "descZh": "空状态触发器文本。"
      }
    ],
    "changelog": [
      {
        "v": "2.2.0",
        "date": "2026-05-27",
        "notes": [
          "Active option now references `accent.default`.",
          "Added `searchable` filter."
        ],
        "notesZh": [
          "当前选项现引用 `accent.default`。",
          "新增 `searchable` 筛选。"
        ]
      },
      {
        "v": "2.1.0",
        "date": "2026-04-09",
        "notes": [
          "Added multi-select with chips."
        ],
        "notesZh": [
          "新增带标签条的多选。"
        ]
      }
    ],
    "repo": "packages/ui/src/Select.tsx",
    "version": "2.2.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "3 days ago",
    "lastCommit": "e4b2c91",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "datepicker",
    "name": "DatePicker",
    "nameZh": "日期/时间选择器",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chartLine",
    "summary": "Calendar and time popover for picking a date, time or range with timezone awareness.",
    "summaryZh": "用于选择日期、时间或区间的日历与时间浮层，支持时区感知。",
    "tags": [
      "form",
      "date",
      "time"
    ],
    "overview": "DatePicker pairs a typeable Input with a calendar popover for selecting points and ranges in the analytics dashboards. The selected day uses accent.default and today is marked with a subtle ring. Always show the timezone for equipment logs so timestamps are never ambiguous across sites.",
    "overviewZh": "DatePicker 将可键入的 Input 与日历浮层配对，用于在分析看板中选择时间点与区间。所选日期采用 accent.default，今日以柔和的环形标记。对于设备日志请始终显示时区，确保跨站点时戳不产生歧义。",
    "dos": [
      "Display the active timezone alongside the value.",
      "Allow direct typing as well as calendar clicks.",
      "Constrain selectable dates with min/max where valid."
    ],
    "dosZh": [
      "在值旁显示当前时区。",
      "既允许日历点击，也允许直接键入。",
      "在合适处用最小/最大值约束可选日期。"
    ],
    "donts": [
      "Omit the timezone on equipment timestamps.",
      "Force calendar clicks when typing is faster.",
      "Use a date range picker for a single date."
    ],
    "dontsZh": [
      "在设备时戳上省略时区。",
      "在键入更快时仍强制使用日历点击。",
      "为单个日期使用区间选择器。"
    ],
    "examples": [
      {
        "id": "datepicker-basic",
        "title": "Single date",
        "titleZh": "单个日期",
        "note": "Calendar popover; today gets a ring.",
        "noteZh": "日历浮层；今日带环形标记。",
        "show": true,
        "demo": "datepicker-basic"
      },
      {
        "id": "datepicker-range",
        "title": "Date range",
        "titleZh": "日期区间",
        "note": "Selected span uses `accent.default`.",
        "noteZh": "所选区间采用 `accent.default`。",
        "show": true,
        "demo": "datepicker-range"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "Date | [Date, Date]",
        "def": "—",
        "required": true,
        "desc": "Selected date or range.",
        "descZh": "所选日期或区间。"
      },
      {
        "name": "onChange",
        "type": "(v: Date | [Date, Date]) => void",
        "def": "—",
        "required": true,
        "desc": "Selection handler.",
        "descZh": "选择处理函数。"
      },
      {
        "name": "mode",
        "type": "'date' | 'datetime' | 'range'",
        "def": "'date'",
        "required": false,
        "desc": "Picker granularity.",
        "descZh": "选择粒度。"
      },
      {
        "name": "min",
        "type": "Date",
        "def": "—",
        "required": false,
        "desc": "Earliest selectable date.",
        "descZh": "最早可选日期。"
      },
      {
        "name": "max",
        "type": "Date",
        "def": "—",
        "required": false,
        "desc": "Latest selectable date.",
        "descZh": "最晚可选日期。"
      },
      {
        "name": "timezone",
        "type": "string",
        "def": "'local'",
        "required": false,
        "desc": "Timezone for display and value.",
        "descZh": "用于显示与取值的时区。"
      }
    ],
    "changelog": [
      {
        "v": "1.8.0",
        "date": "2026-05-24",
        "notes": [
          "Today marker now uses a subtle `accent.default` ring.",
          "Added `timezone` prop."
        ],
        "notesZh": [
          "今日标记现使用柔和的 `accent.default` 环形。",
          "新增 `timezone` 属性。"
        ]
      },
      {
        "v": "1.7.0",
        "date": "2026-04-02",
        "notes": [
          "Added range mode."
        ],
        "notesZh": [
          "新增区间模式。"
        ]
      }
    ],
    "repo": "packages/ui/src/DatePicker.tsx",
    "version": "1.8.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "1 week ago",
    "lastCommit": "f1c6d38",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "transfer",
    "name": "Transfer",
    "nameZh": "穿梭框",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "beta",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "diff",
    "summary": "Dual-list control for moving items between a source and a selected set.",
    "summaryZh": "用于在源列表与已选集合之间移动条目的双列表控件。",
    "tags": [
      "form",
      "list",
      "selection"
    ],
    "overview": "Transfer presents two searchable panes with arrow controls to shuttle items between them, ideal for assigning recipes, permissions or sensor channels. Both panes share the Input border and the move buttons draw their active fill from accent.default. Use it only when users need to curate a sizable subset; for a handful of items, multi-select Select is lighter.",
    "overviewZh": "Transfer 呈现两个可搜索的面板，并用箭头控件在二者间移动条目，适合分配配方、权限或传感器通道。两个面板共用 Input 边框，移动按钮的激活填充取自 accent.default。仅当用户需要从较大集合中挑选子集时使用；条目寥寥时，多选 Select 更轻量。",
    "dos": [
      "Make both panes searchable when lists are long.",
      "Show counts so users track how many are selected.",
      "Support bulk move-all and clear-all actions."
    ],
    "dosZh": [
      "列表较长时让两个面板均可搜索。",
      "显示计数，让用户掌握已选数量。",
      "支持全部移入与全部清除的批量操作。"
    ],
    "donts": [
      "Use Transfer for fewer than ~10 items.",
      "Hide the selected count from the user.",
      "Block keyboard navigation between panes."
    ],
    "dontsZh": [
      "对少于约 10 个条目使用 Transfer。",
      "对用户隐藏已选计数。",
      "阻断面板间的键盘导航。"
    ],
    "examples": [
      {
        "id": "transfer-basic",
        "title": "Basic transfer",
        "titleZh": "基础穿梭框",
        "note": "Two panes with arrow controls.",
        "noteZh": "两个面板配箭头控件。",
        "show": true,
        "demo": "transfer-basic"
      },
      {
        "id": "transfer-search",
        "title": "Searchable",
        "titleZh": "可搜索",
        "note": "Filter both panes independently.",
        "noteZh": "可分别筛选两个面板。",
        "show": false,
        "demo": "transfer-search"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "TransferItem[]",
        "def": "—",
        "required": true,
        "desc": "All available items.",
        "descZh": "所有可用条目。"
      },
      {
        "name": "selected",
        "type": "string[]",
        "def": "[]",
        "required": true,
        "desc": "IDs in the selected pane.",
        "descZh": "已选面板中的条目 ID。"
      },
      {
        "name": "onChange",
        "type": "(ids: string[]) => void",
        "def": "—",
        "required": true,
        "desc": "Selection change handler.",
        "descZh": "选择变更处理函数。"
      },
      {
        "name": "searchable",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Adds filter fields to both panes.",
        "descZh": "为两个面板添加筛选字段。"
      },
      {
        "name": "titles",
        "type": "[string, string]",
        "def": "—",
        "required": false,
        "desc": "Source and target pane headings.",
        "descZh": "源面板与目标面板的标题。"
      }
    ],
    "changelog": [
      {
        "v": "0.5.0",
        "date": "2026-06-01",
        "notes": [
          "Move buttons now reference `accent.default`.",
          "Beta: pane API may still change."
        ],
        "notesZh": [
          "移动按钮现引用 `accent.default`。",
          "测试版：面板 API 仍可能调整。"
        ]
      },
      {
        "v": "0.4.0",
        "date": "2026-05-06",
        "notes": [
          "Initial beta with search support."
        ],
        "notesZh": [
          "首个测试版，支持搜索。"
        ]
      }
    ],
    "repo": "packages/ui/src/Transfer.tsx",
    "version": "0.5.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "yesterday",
    "lastCommit": "a8d5f60",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "slider",
    "name": "Slider",
    "nameZh": "滑块",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "sliders",
    "summary": "Drag-to-set control for a bounded value or range along a continuous track.",
    "summaryZh": "沿连续轨道拖动设定有界数值或区间的控件。",
    "tags": [
      "form",
      "range",
      "control"
    ],
    "overview": "Slider lets users set a value within a known range by dragging a handle along a track. The filled portion uses accent.default and the handle lifts on focus with a ring for keyboard users. Pair it with a NumberInput when operators need precise values rather than approximate ones.",
    "overviewZh": "Slider 让用户在已知范围内通过沿轨道拖动手柄来设定数值。已填充部分采用 accent.default，聚焦时手柄抬起并带环形以便键盘用户操作。当操作员需要精确而非近似数值时，请与 NumberInput 搭配使用。",
    "dos": [
      "Show the current value as the user drags.",
      "Use sensible step granularity for the quantity.",
      "Pair with NumberInput when precision matters."
    ],
    "dosZh": [
      "拖动时显示当前数值。",
      "为该量值采用合理的步长粒度。",
      "需要精确时与 NumberInput 搭配。"
    ],
    "donts": [
      "Use a slider where exact entry is required.",
      "Hide the value while the handle moves.",
      "Make the track or handle too small to grab."
    ],
    "dontsZh": [
      "在必须精确录入处使用滑块。",
      "手柄移动时隐藏数值。",
      "把轨道或手柄做得太小而难以抓取。"
    ],
    "examples": [
      {
        "id": "slider-basic",
        "title": "Single value",
        "titleZh": "单值",
        "note": "Filled track uses `accent.default`.",
        "noteZh": "已填充轨道采用 `accent.default`。",
        "show": true,
        "demo": "slider-basic"
      },
      {
        "id": "slider-range",
        "title": "Range",
        "titleZh": "区间",
        "note": "Two handles bound a span.",
        "noteZh": "双手柄界定一段区间。",
        "show": true,
        "demo": "slider-range"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "number | [number, number]",
        "def": "—",
        "required": true,
        "desc": "Current value or range.",
        "descZh": "当前值或区间。"
      },
      {
        "name": "onChange",
        "type": "(v: number | [number, number]) => void",
        "def": "—",
        "required": true,
        "desc": "Change handler.",
        "descZh": "变更处理函数。"
      },
      {
        "name": "min",
        "type": "number",
        "def": "0",
        "required": false,
        "desc": "Track lower bound.",
        "descZh": "轨道下限。"
      },
      {
        "name": "max",
        "type": "number",
        "def": "100",
        "required": false,
        "desc": "Track upper bound.",
        "descZh": "轨道上限。"
      },
      {
        "name": "step",
        "type": "number",
        "def": "1",
        "required": false,
        "desc": "Drag increment.",
        "descZh": "拖动增量。"
      },
      {
        "name": "showValue",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Display the live value label.",
        "descZh": "显示实时数值标签。"
      }
    ],
    "changelog": [
      {
        "v": "1.6.0",
        "date": "2026-05-20",
        "notes": [
          "Filled track now references `accent.default`.",
          "Added range mode with two handles."
        ],
        "notesZh": [
          "已填充轨道现引用 `accent.default`。",
          "新增双手柄区间模式。"
        ]
      },
      {
        "v": "1.5.0",
        "date": "2026-03-30",
        "notes": [
          "Improved focus ring for keyboard control."
        ],
        "notesZh": [
          "改进键盘操作时的聚焦环。"
        ]
      }
    ],
    "repo": "packages/ui/src/Slider.tsx",
    "version": "1.6.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "5 days ago",
    "lastCommit": "b2e9c47",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "switch",
    "name": "Switch",
    "nameZh": "开关",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "power",
    "summary": "Toggle for an immediate on/off setting that takes effect without a save step.",
    "summaryZh": "用于即时开/关设置的切换控件，无需保存即可生效。",
    "tags": [
      "form",
      "toggle",
      "boolean"
    ],
    "overview": "Switch flips a single boolean setting that applies instantly, like enabling an alarm or a data feed. The on state fills with accent.default and the thumb slides with a short transition. Use it only for settings that take effect immediately; for choices confirmed on submit, use Checkbox.",
    "overviewZh": "Switch 切换一个即时生效的布尔设置，例如启用告警或数据源。开启状态以 accent.default 填充，滑块带短促过渡滑动。仅用于即时生效的设置；对于提交时才确认的选择，请使用 Checkbox。",
    "dos": [
      "Use Switch only for settings that apply instantly.",
      "Label the setting, not the on/off state.",
      "Reflect the real system state, not an optimistic guess."
    ],
    "dosZh": [
      "仅对即时生效的设置使用 Switch。",
      "为设置本身命名，而非开/关状态。",
      "反映系统真实状态，而非乐观猜测。"
    ],
    "donts": [
      "Use a switch where a save step is expected — use Checkbox.",
      "Require a separate submit after toggling.",
      "Use a switch for mutually exclusive choices."
    ],
    "dontsZh": [
      "在需要保存步骤处使用开关——应改用 Checkbox。",
      "切换后还要求单独提交。",
      "用开关表达互斥选项。"
    ],
    "examples": [
      {
        "id": "switch-basic",
        "title": "Basic switch",
        "titleZh": "基础开关",
        "note": "On state fills with `accent.default`.",
        "noteZh": "开启状态以 `accent.default` 填充。",
        "show": true,
        "demo": "switch-basic"
      },
      {
        "id": "switch-label",
        "title": "With label",
        "titleZh": "带标签",
        "note": "Label names the setting, not the state.",
        "noteZh": "标签命名设置而非状态。",
        "show": true,
        "demo": "switch-label"
      }
    ],
    "props": [
      {
        "name": "checked",
        "type": "boolean",
        "def": "false",
        "required": true,
        "desc": "On/off state.",
        "descZh": "开/关状态。"
      },
      {
        "name": "onChange",
        "type": "(checked: boolean) => void",
        "def": "—",
        "required": true,
        "desc": "Toggle handler.",
        "descZh": "切换处理函数。"
      },
      {
        "name": "label",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Setting label text.",
        "descZh": "设置标签文本。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md'",
        "def": "'md'",
        "required": false,
        "desc": "Control size.",
        "descZh": "控件尺寸。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Prevents interaction.",
        "descZh": "阻止交互。"
      }
    ],
    "changelog": [
      {
        "v": "1.5.1",
        "date": "2026-05-17",
        "notes": [
          "On fill now references `accent.default`.",
          "Reduced thumb transition to 120ms."
        ],
        "notesZh": [
          "开启填充现引用 `accent.default`。",
          "滑块过渡缩短至 120ms。"
        ]
      },
      {
        "v": "1.5.0",
        "date": "2026-04-01",
        "notes": [
          "Added `sm` size."
        ],
        "notesZh": [
          "新增 `sm` 尺寸。"
        ]
      }
    ],
    "repo": "packages/ui/src/Switch.tsx",
    "version": "1.5.1",
    "lastEditBy": "m.okafor",
    "lastEditAt": "1 week ago",
    "lastCommit": "c6a1f93",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "radio",
    "name": "Radio",
    "nameZh": "单选框",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "check",
    "summary": "Single-choice control for picking exactly one option from a small visible set.",
    "summaryZh": "从少量可见选项中恰好选取一项的单选控件。",
    "tags": [
      "form",
      "choice",
      "single"
    ],
    "overview": "Radio lets users choose one option from a short list where seeing every choice at once aids the decision. The selected dot uses accent.default and the group shares spacing.inset.md between items. Use it for two to five mutually exclusive options; beyond that, Select scales better.",
    "overviewZh": "Radio 让用户从短列表中选取一项，适合需要同时看到所有选项以辅助决策的场景。选中圆点采用 accent.default，组内各项之间共用 spacing.inset.md。适用于二至五个互斥选项；超出此数时 Select 更易扩展。",
    "dos": [
      "Use Radio for two to five mutually exclusive options.",
      "Pre-select a sensible default when one exists.",
      "Keep options short enough to scan at a glance."
    ],
    "dosZh": [
      "对二至五个互斥选项使用 Radio。",
      "存在合理默认值时预先选中。",
      "让选项足够简短，一眼即可浏览。"
    ],
    "donts": [
      "Use Radio when multiple choices are allowed — use Checkbox.",
      "Use Radio for more than ~5 options — use Select.",
      "Leave a group with no option selectable as the default."
    ],
    "dontsZh": [
      "在允许多选时使用 Radio——应改用 Checkbox。",
      "对超过约 5 个选项使用 Radio——应改用 Select。",
      "让某组没有任何可作为默认的可选项。"
    ],
    "examples": [
      {
        "id": "radio-basic",
        "title": "Radio group",
        "titleZh": "单选组",
        "note": "Selected dot uses `accent.default`.",
        "noteZh": "选中圆点采用 `accent.default`。",
        "show": true,
        "demo": "radio-basic"
      },
      {
        "id": "radio-cards",
        "title": "Card radios",
        "titleZh": "卡片式单选",
        "note": "Richer option tiles for setup flows.",
        "noteZh": "用于配置流程的更丰富选项卡片。",
        "show": false,
        "demo": "radio-cards"
      }
    ],
    "props": [
      {
        "name": "options",
        "type": "RadioOption[]",
        "def": "—",
        "required": true,
        "desc": "Mutually exclusive choices.",
        "descZh": "互斥的选项。"
      },
      {
        "name": "value",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Selected option value.",
        "descZh": "已选选项值。"
      },
      {
        "name": "onChange",
        "type": "(v: string) => void",
        "def": "—",
        "required": true,
        "desc": "Selection handler.",
        "descZh": "选择处理函数。"
      },
      {
        "name": "orientation",
        "type": "'vertical' | 'horizontal'",
        "def": "'vertical'",
        "required": false,
        "desc": "Layout direction.",
        "descZh": "排布方向。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Disables the whole group.",
        "descZh": "禁用整个组。"
      }
    ],
    "changelog": [
      {
        "v": "1.4.0",
        "date": "2026-05-15",
        "notes": [
          "Selected dot now references `accent.default`.",
          "Added horizontal orientation."
        ],
        "notesZh": [
          "选中圆点现引用 `accent.default`。",
          "新增水平排布。"
        ]
      },
      {
        "v": "1.3.0",
        "date": "2026-03-22",
        "notes": [
          "Improved group keyboard navigation."
        ],
        "notesZh": [
          "改进组内键盘导航。"
        ]
      }
    ],
    "repo": "packages/ui/src/Radio.tsx",
    "version": "1.4.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "4 days ago",
    "lastCommit": "d7b3e58",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "checkbox",
    "name": "Checkbox",
    "nameZh": "复选框",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "check",
    "summary": "Multi-select control for toggling independent options, with an indeterminate state.",
    "summaryZh": "用于切换独立选项的多选控件，支持半选状态。",
    "tags": [
      "form",
      "choice",
      "multiple"
    ],
    "overview": "Checkbox toggles one or more independent options that are confirmed when the form is submitted. The checked box fills with accent.default and a parent can show the indeterminate state when only some children are checked. Use it for non-exclusive selections and for single yes/no consent that needs a save step.",
    "overviewZh": "Checkbox 切换一个或多个独立选项，并在表单提交时确认。选中的方框以 accent.default 填充，当仅部分子项被选中时，父项可显示半选状态。适用于非互斥选择，以及需要保存步骤的单项是/否确认。",
    "dos": [
      "Use Checkbox for non-exclusive, multi-select options.",
      "Use the indeterminate state for partial parent selection.",
      "Confirm checkbox state on submit, not instantly."
    ],
    "dosZh": [
      "对非互斥的多选选项使用 Checkbox。",
      "用半选状态表示父项的部分选中。",
      "复选状态在提交时确认，而非即时生效。"
    ],
    "donts": [
      "Use Checkbox for an instant setting — use Switch.",
      "Use Checkbox for mutually exclusive choices — use Radio.",
      "Hide partial selection by skipping the indeterminate state."
    ],
    "dontsZh": [
      "对即时生效的设置使用 Checkbox——应改用 Switch。",
      "对互斥选项使用 Checkbox——应改用 Radio。",
      "省略半选状态而隐藏部分选中。"
    ],
    "examples": [
      {
        "id": "checkbox-basic",
        "title": "Basic checkbox",
        "titleZh": "基础复选框",
        "note": "Checked fill uses `accent.default`.",
        "noteZh": "选中填充采用 `accent.default`。",
        "show": true,
        "demo": "checkbox-basic"
      },
      {
        "id": "checkbox-group",
        "title": "Group with parent",
        "titleZh": "带父项的组",
        "note": "Parent shows the indeterminate state.",
        "noteZh": "父项显示半选状态。",
        "show": true,
        "demo": "checkbox-group"
      }
    ],
    "props": [
      {
        "name": "checked",
        "type": "boolean",
        "def": "false",
        "required": true,
        "desc": "Checked state.",
        "descZh": "选中状态。"
      },
      {
        "name": "onChange",
        "type": "(checked: boolean) => void",
        "def": "—",
        "required": true,
        "desc": "Toggle handler.",
        "descZh": "切换处理函数。"
      },
      {
        "name": "indeterminate",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Partial-selection state.",
        "descZh": "部分选中状态。"
      },
      {
        "name": "label",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Option label text.",
        "descZh": "选项标签文本。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Prevents interaction.",
        "descZh": "阻止交互。"
      }
    ],
    "changelog": [
      {
        "v": "1.5.0",
        "date": "2026-05-23",
        "notes": [
          "Checked fill now references `accent.default`.",
          "Added indeterminate state."
        ],
        "notesZh": [
          "选中填充现引用 `accent.default`。",
          "新增半选状态。"
        ]
      },
      {
        "v": "1.4.0",
        "date": "2026-03-25",
        "notes": [
          "Improved focus ring contrast."
        ],
        "notesZh": [
          "改进聚焦环对比度。"
        ]
      }
    ],
    "repo": "packages/ui/src/Checkbox.tsx",
    "version": "1.5.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "3 days ago",
    "lastCommit": "e9c4a82",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "upload",
    "name": "Upload",
    "nameZh": "上传",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "upload",
    "summary": "Drag-and-drop or browse control for adding files, with progress and validation.",
    "summaryZh": "用于添加文件的拖放或浏览控件，带进度与校验。",
    "tags": [
      "form",
      "file",
      "dropzone"
    ],
    "overview": "Upload accepts files via drag-and-drop onto a dashed dropzone or a browse button, then lists each item with progress and status. The dropzone border uses color.border.default and brightens to accent.default on drag-over. Always state accepted types and the size limit up front so failures are rare.",
    "overviewZh": "Upload 支持将文件拖放到虚线投放区或通过浏览按钮添加，随后逐项列出进度与状态。投放区边框采用 color.border.default，拖入悬停时增亮为 accent.default。请预先说明可接受的类型与大小上限，以减少失败。",
    "dos": [
      "State accepted file types and the size limit up front.",
      "Show per-file progress and a clear error on failure.",
      "Let users retry or remove a failed upload."
    ],
    "dosZh": [
      "预先说明可接受的文件类型与大小上限。",
      "显示每个文件的进度，失败时给出明确错误。",
      "允许用户重试或移除失败的上传。"
    ],
    "donts": [
      "Accept files silently without a size or type guard.",
      "Hide upload progress on slow connections.",
      "Block the UI while large files transfer."
    ],
    "dontsZh": [
      "无大小或类型校验便静默接收文件。",
      "在慢速连接下隐藏上传进度。",
      "大文件传输时阻塞界面。"
    ],
    "examples": [
      {
        "id": "upload-basic",
        "title": "Dropzone",
        "titleZh": "投放区",
        "note": "Dashed border brightens on drag-over.",
        "noteZh": "拖入悬停时虚线边框增亮。",
        "show": true,
        "demo": "upload-basic"
      },
      {
        "id": "upload-list",
        "title": "File list",
        "titleZh": "文件列表",
        "note": "Per-file progress and status.",
        "noteZh": "每个文件的进度与状态。",
        "show": true,
        "demo": "upload-list"
      }
    ],
    "props": [
      {
        "name": "onUpload",
        "type": "(files: File[]) => void",
        "def": "—",
        "required": true,
        "desc": "Files-added handler.",
        "descZh": "文件添加处理函数。"
      },
      {
        "name": "accept",
        "type": "string",
        "def": "'*'",
        "required": false,
        "desc": "Accepted MIME types.",
        "descZh": "可接受的 MIME 类型。"
      },
      {
        "name": "multiple",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Allow multiple files.",
        "descZh": "允许多个文件。"
      },
      {
        "name": "maxSize",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Per-file size limit in bytes.",
        "descZh": "每个文件的大小上限（字节）。"
      },
      {
        "name": "disabled",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Disables the dropzone.",
        "descZh": "禁用投放区。"
      }
    ],
    "changelog": [
      {
        "v": "1.6.0",
        "date": "2026-05-26",
        "notes": [
          "Drag-over border now references `accent.default`.",
          "Added per-file retry."
        ],
        "notesZh": [
          "拖入悬停边框现引用 `accent.default`。",
          "新增按文件重试。"
        ]
      },
      {
        "v": "1.5.0",
        "date": "2026-04-07",
        "notes": [
          "Added `maxSize` validation."
        ],
        "notesZh": [
          "新增 `maxSize` 校验。"
        ]
      }
    ],
    "repo": "packages/ui/src/Upload.tsx",
    "version": "1.6.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "6 days ago",
    "lastCommit": "f3a7d19",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "colorpicker",
    "name": "ColorPicker",
    "nameZh": "取色器",
    "category": "Data entry",
    "categoryZh": "录入",
    "status": "beta",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "image",
    "summary": "Popover for selecting a color via spectrum, hex entry or a preset swatch set.",
    "summaryZh": "通过色谱、十六进制录入或预设色块选择颜色的浮层。",
    "tags": [
      "form",
      "color",
      "swatch"
    ],
    "overview": "ColorPicker opens a popover with a spectrum area, hex/RGBA input and a row of preset swatches, mainly for theming and chart-series customization. The trigger shows the current color over a checkerboard when alpha is below full, and the popover border uses color.border.default. Offer brand-aligned presets so most picks stay on-palette.",
    "overviewZh": "ColorPicker 打开一个含色谱区域、十六进制/RGBA 输入与一排预设色块的浮层，主要用于主题定制与图表系列配色。当透明度未满时，触发器在棋盘格背景上显示当前颜色，浮层边框采用 color.border.default。请提供符合品牌的预设，让多数选择保持在调色板内。",
    "dos": [
      "Offer brand-aligned preset swatches first.",
      "Show alpha over a checkerboard when transparency applies.",
      "Allow exact hex or RGBA entry for precision."
    ],
    "dosZh": [
      "优先提供符合品牌的预设色块。",
      "涉及透明度时在棋盘格上显示 alpha。",
      "允许精确的十六进制或 RGBA 录入。"
    ],
    "donts": [
      "Force spectrum dragging when a hex value is known.",
      "Omit presets and leave users to free-pick off-palette.",
      "Hide the current alpha value from the user."
    ],
    "dontsZh": [
      "已知十六进制值时仍强制拖动色谱。",
      "省略预设，放任用户选出偏离调色板的颜色。",
      "对用户隐藏当前 alpha 值。"
    ],
    "examples": [
      {
        "id": "colorpicker-basic",
        "title": "Basic picker",
        "titleZh": "基础取色器",
        "note": "Spectrum plus hex input.",
        "noteZh": "色谱加十六进制输入。",
        "show": true,
        "demo": "colorpicker-basic"
      },
      {
        "id": "colorpicker-presets",
        "title": "Preset swatches",
        "titleZh": "预设色块",
        "note": "Brand-aligned swatch row.",
        "noteZh": "符合品牌的色块行。",
        "show": true,
        "demo": "colorpicker-presets"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Current color (hex or rgba).",
        "descZh": "当前颜色（十六进制或 rgba）。"
      },
      {
        "name": "onChange",
        "type": "(c: string) => void",
        "def": "—",
        "required": true,
        "desc": "Color change handler.",
        "descZh": "颜色变更处理函数。"
      },
      {
        "name": "presets",
        "type": "string[]",
        "def": "[]",
        "required": false,
        "desc": "Preset swatch colors.",
        "descZh": "预设色块颜色。"
      },
      {
        "name": "alpha",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Enable the alpha channel.",
        "descZh": "启用 alpha 通道。"
      },
      {
        "name": "format",
        "type": "'hex' | 'rgba'",
        "def": "'hex'",
        "required": false,
        "desc": "Output value format.",
        "descZh": "输出值格式。"
      }
    ],
    "changelog": [
      {
        "v": "0.4.0",
        "date": "2026-06-03",
        "notes": [
          "Trigger now shows alpha over a checkerboard.",
          "Beta: format API may still change."
        ],
        "notesZh": [
          "触发器现于棋盘格上显示 alpha。",
          "测试版：format API 仍可能调整。"
        ]
      },
      {
        "v": "0.3.0",
        "date": "2026-05-08",
        "notes": [
          "Added preset swatch row."
        ],
        "notesZh": [
          "新增预设色块行。"
        ]
      }
    ],
    "repo": "packages/ui/src/ColorPicker.tsx",
    "version": "0.4.0",
    "lastEditBy": "m.okafor",
    "lastEditAt": "yesterday",
    "lastCommit": "a1d6c73",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "table",
    "name": "Table",
    "nameZh": "表格",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": true,
    "cautionReason": "Table is shared across every product surface — HMI alarm logs, analytics grids, and AI app data views. Schema, sorting, and density changes ripple into hundreds of dependent views, so any token or API change must be coordinated across all four brand themes.",
    "cautionReasonZh": "表格被所有产品界面共用——HMI 报警日志、分析网格、AI 应用数据视图。列结构、排序与密度的改动会波及数百个依赖视图，因此任何令牌或 API 变更都必须在四套品牌主题间协同评估。",
    "icon": "table",
    "summary": "Dense, sortable data grid with selection, fixed columns, and virtualized rows for large datasets.",
    "summaryZh": "支持排序、选择、固定列与行虚拟化的高密度数据网格，适用于大规模数据集。",
    "tags": [
      "data",
      "grid",
      "sortable",
      "virtualized",
      "selection"
    ],
    "overview": "Use Table for structured, scannable records where columns carry meaning; reserve it for tabular data rather than card layouts. Apply density='compact' for HMI and monitoring contexts and rely on color.border.default for row separators and spacing.inset.sm for cell padding. For sets above ~200 rows enable virtualization so the alarm and telemetry views stay responsive.",
    "overviewZh": "当各列均承载明确语义、需要快速扫读结构化记录时使用 Table；它适用于表格数据而非卡片布局。在 HMI 与监控场景中使用 density='compact'，行分隔依赖 color.border.default，单元格内边距使用 spacing.inset.sm。当数据超过约 200 行时启用虚拟化，保持报警与遥测视图的响应速度。",
    "dos": [
      "Right-align numeric and metric columns and keep units consistent within a column.",
      "Enable virtualization and a sticky header for datasets larger than a few hundred rows.",
      "Provide an explicit empty state with guidance instead of a blank grid."
    ],
    "dosZh": [
      "数值与指标列右对齐，并在同一列内保持单位一致。",
      "对数百行以上的数据集启用虚拟化与吸顶表头。",
      "为空数据提供带引导文案的空状态，而非留白网格。"
    ],
    "donts": [
      "Don't nest interactive controls in many cells; it hurts scannability and keyboard flow.",
      "Don't use Table for fewer than three columns where a list would read better.",
      "Don't hardcode pixel borders — use color.border.default so themes stay consistent."
    ],
    "dontsZh": [
      "不要在大量单元格中嵌入交互控件，会损害扫读性与键盘操作流。",
      "当列少于三列、列表更易读时，不要使用 Table。",
      "不要硬编码像素边框——使用 color.border.default 以保持主题一致。"
    ],
    "examples": [
      {
        "id": "table-basic",
        "title": "Sortable data grid",
        "titleZh": "可排序数据网格",
        "note": "Basic columns with click-to-sort headers and zebra rows.",
        "noteZh": "基础列配合点击排序表头与斑马行。",
        "show": true,
        "demo": "table-basic"
      },
      {
        "id": "table-selection",
        "title": "Row selection",
        "titleZh": "行选择",
        "note": "Checkbox column with select-all and bulk-action toolbar.",
        "noteZh": "复选框列配合全选与批量操作工具栏。",
        "show": true,
        "demo": "table-selection"
      },
      {
        "id": "table-virtualized",
        "title": "Virtualized large set",
        "titleZh": "虚拟化大数据集",
        "note": "10k telemetry rows rendered with windowed virtualization.",
        "noteZh": "通过窗口虚拟化渲染一万行遥测数据。",
        "show": false,
        "demo": "table-virtualized"
      }
    ],
    "props": [
      {
        "name": "columns",
        "type": "Column<T>[]",
        "def": "—",
        "required": true,
        "desc": "Column definitions including key, header, width, and optional cell renderer.",
        "descZh": "列定义，包含 key、表头、宽度及可选的单元格渲染器。"
      },
      {
        "name": "data",
        "type": "T[]",
        "def": "[]",
        "required": true,
        "desc": "Row records rendered in source order unless a sort is applied.",
        "descZh": "行记录，未应用排序时按原始顺序渲染。"
      },
      {
        "name": "density",
        "type": "'comfortable' | 'compact'",
        "def": "'comfortable'",
        "required": false,
        "desc": "Row height and cell padding preset; use compact for HMI grids.",
        "descZh": "行高与单元格内边距预设；HMI 网格建议使用 compact。"
      },
      {
        "name": "selectable",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Renders a leading checkbox column with select-all support.",
        "descZh": "渲染带全选支持的前置复选框列。"
      },
      {
        "name": "virtualized",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Windows row rendering for large datasets; pairs with a fixed height.",
        "descZh": "对大数据集启用行窗口渲染；需配合固定高度。"
      },
      {
        "name": "onSortChange",
        "type": "(sort: SortState) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when a sortable header is toggled.",
        "descZh": "切换可排序表头时触发。"
      }
    ],
    "changelog": [
      {
        "v": "3.2.0",
        "date": "2026-04-18",
        "notes": [
          "Added windowed virtualization for datasets over 200 rows.",
          "Sticky header now respects nested scroll containers."
        ],
        "notesZh": [
          "为超过 200 行的数据集新增窗口虚拟化。",
          "吸顶表头现已适配嵌套滚动容器。"
        ]
      },
      {
        "v": "3.1.0",
        "date": "2026-02-09",
        "notes": [
          "Introduced compact density preset for HMI contexts."
        ],
        "notesZh": [
          "新增适用于 HMI 场景的 compact 密度预设。"
        ]
      }
    ],
    "repo": "packages/ui/src/Table.tsx",
    "version": "3.2.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "2 days ago",
    "lastCommit": "a3f9c21",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "modal",
    "name": "Modal",
    "nameZh": "弹窗",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": true,
    "cautionReason": "Modal owns the global focus trap, scroll lock, and overlay layer used by confirmations, forms, and destructive flows across all products. Changes to its z-index, dismissal, or animation behavior affect every dialog in the system.",
    "cautionReasonZh": "Modal 掌管全局焦点陷阱、滚动锁定与遮罩层，被所有产品的确认、表单与危险操作流程复用。其层级、关闭行为或动画的改动会影响系统中的每一个对话框。",
    "icon": "layers",
    "summary": "Centered overlay dialog with focus trapping, scroll lock, and configurable dismissal.",
    "summaryZh": "居中遮罩对话框，具备焦点陷阱、滚动锁定与可配置的关闭方式。",
    "tags": [
      "overlay",
      "dialog",
      "focus-trap",
      "confirmation"
    ],
    "overview": "Use Modal for focused, interrupting tasks such as confirmations and short forms that must block the underlying view. Keep content concise, anchor the primary action to the right, and use radius.control on the surface with color.overlay.scrim for the backdrop. Avoid stacking modals — for secondary detail prefer Drawer so the user keeps context.",
    "overviewZh": "Modal 用于必须打断并阻塞底层视图的聚焦型任务，如确认与简短表单。内容应精炼，主操作锚定在右侧，弹窗表面使用 radius.control，背景遮罩使用 color.overlay.scrim。避免弹窗叠加——次级详情建议使用 Drawer 以保留上下文。",
    "dos": [
      "Trap focus inside the modal and return focus to the trigger on close.",
      "Place the primary action last (right-most) and label it with the actual verb.",
      "Allow Esc and scrim click to dismiss for non-destructive dialogs."
    ],
    "dosZh": [
      "将焦点限制在弹窗内部，并在关闭时把焦点归还触发元素。",
      "把主操作放在最后（最右侧），并用真实动词命名按钮。",
      "对非危险对话框允许 Esc 与点击遮罩关闭。"
    ],
    "donts": [
      "Don't stack modals on top of modals; route deeper detail to a Drawer instead.",
      "Don't allow scrim click to dismiss destructive confirmations.",
      "Don't put long, scrolling content in a modal — use a page or drawer."
    ],
    "dontsZh": [
      "不要在弹窗上再叠加弹窗；更深层的详情应改用 Drawer。",
      "不要允许通过点击遮罩关闭危险操作的确认框。",
      "不要在弹窗内放置需长滚动的内容——应改用页面或抽屉。"
    ],
    "examples": [
      {
        "id": "modal-confirm",
        "title": "Confirmation dialog",
        "titleZh": "确认对话框",
        "note": "Destructive confirm with disabled scrim dismissal.",
        "noteZh": "危险操作确认，禁用遮罩关闭。",
        "show": true,
        "demo": "modal-confirm"
      },
      {
        "id": "modal-form",
        "title": "Form in modal",
        "titleZh": "弹窗内表单",
        "note": "Short create form with footer actions.",
        "noteZh": "带底部操作的简短创建表单。",
        "show": true,
        "demo": "modal-form"
      }
    ],
    "props": [
      {
        "name": "open",
        "type": "boolean",
        "def": "false",
        "required": true,
        "desc": "Controls visibility; the component is fully controlled.",
        "descZh": "控制显隐；该组件为完全受控。"
      },
      {
        "name": "onClose",
        "type": "() => void",
        "def": "—",
        "required": true,
        "desc": "Called on Esc, scrim click, or close button when dismissal is allowed.",
        "descZh": "在允许关闭时，由 Esc、点击遮罩或关闭按钮触发。"
      },
      {
        "name": "title",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Header title; sets the accessible dialog label.",
        "descZh": "头部标题；同时设置对话框的无障碍标签。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg'",
        "def": "'md'",
        "required": false,
        "desc": "Max width preset for the dialog surface.",
        "descZh": "对话框表面的最大宽度预设。"
      },
      {
        "name": "dismissible",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "When false, disables Esc and scrim-click dismissal.",
        "descZh": "为 false 时禁用 Esc 与点击遮罩关闭。"
      }
    ],
    "changelog": [
      {
        "v": "2.6.1",
        "date": "2026-05-02",
        "notes": [
          "Focus now reliably returns to the trigger element on close.",
          "Scrim opacity aligned to color.overlay.scrim token."
        ],
        "notesZh": [
          "关闭时焦点现可稳定归还触发元素。",
          "遮罩透明度对齐 color.overlay.scrim 令牌。"
        ]
      }
    ],
    "repo": "packages/ui/src/Modal.tsx",
    "version": "2.6.1",
    "lastEditBy": "m.okafor",
    "lastEditAt": "5 days ago",
    "lastCommit": "7d2e0b8",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "loading",
    "name": "Loading",
    "nameZh": "加载",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "refresh",
    "summary": "Indeterminate spinner and skeleton placeholders for pending and in-flight states.",
    "summaryZh": "用于等待与进行中状态的不确定型加载指示器与骨架占位。",
    "tags": [
      "spinner",
      "skeleton",
      "async",
      "feedback"
    ],
    "overview": "Use Loading to signal pending work; choose skeletons for first content load and the spinner for short in-place actions. Tint the indicator with accent.default and keep skeleton blocks at radius.control matching the content they replace. Defer showing any indicator for ~200ms to avoid flicker on fast responses.",
    "overviewZh": "Loading 用于表示进行中的工作；首屏内容加载使用骨架屏，短时就地操作使用旋转指示器。指示器使用 accent.default 着色，骨架块使用与所替代内容一致的 radius.control。建议延迟约 200 毫秒再显示指示器，避免快速响应时的闪烁。",
    "dos": [
      "Prefer skeletons that mirror the final layout for initial content loads.",
      "Delay the indicator briefly so fast responses don't flash a spinner.",
      "Pair long operations with a label describing what is loading."
    ],
    "dosZh": [
      "首屏内容加载优先使用与最终布局一致的骨架屏。",
      "短暂延迟显示指示器，使快速响应不会闪现旋转图标。",
      "为耗时操作配上说明正在加载内容的文案。"
    ],
    "donts": [
      "Don't block an entire page when only one region is updating.",
      "Don't show a spinner with no context for operations over a few seconds.",
      "Don't use a determinate-looking bar for unknown durations."
    ],
    "dontsZh": [
      "当仅有一个区域在更新时，不要遮挡整页。",
      "对超过数秒的操作，不要显示无任何上下文的旋转图标。",
      "不要用看似确定进度的进度条表示未知时长。"
    ],
    "examples": [
      {
        "id": "loading-spinner",
        "title": "Inline spinner",
        "titleZh": "内联旋转指示器",
        "note": "Small spinner for button and in-place actions.",
        "noteZh": "用于按钮与就地操作的小型旋转指示器。",
        "show": true,
        "demo": "loading-spinner"
      },
      {
        "id": "loading-skeleton",
        "title": "Skeleton placeholder",
        "titleZh": "骨架占位",
        "note": "Card skeleton mirroring the loaded layout.",
        "noteZh": "与加载后布局一致的卡片骨架。",
        "show": true,
        "demo": "loading-skeleton"
      }
    ],
    "props": [
      {
        "name": "variant",
        "type": "'spinner' | 'skeleton' | 'dots'",
        "def": "'spinner'",
        "required": false,
        "desc": "Visual style of the loading indicator.",
        "descZh": "加载指示器的视觉样式。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg'",
        "def": "'md'",
        "required": false,
        "desc": "Indicator size; affects spinner diameter or skeleton scale.",
        "descZh": "指示器尺寸；影响旋转图标直径或骨架比例。"
      },
      {
        "name": "label",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Accessible status text announced to screen readers.",
        "descZh": "向屏幕阅读器播报的无障碍状态文案。"
      },
      {
        "name": "delayMs",
        "type": "number",
        "def": "200",
        "required": false,
        "desc": "Milliseconds to wait before rendering to prevent flicker.",
        "descZh": "渲染前等待的毫秒数，用于防止闪烁。"
      }
    ],
    "changelog": [
      {
        "v": "1.9.0",
        "date": "2026-03-14",
        "notes": [
          "Added dots variant.",
          "Default render delay raised to 200ms."
        ],
        "notesZh": [
          "新增 dots 变体。",
          "默认渲染延迟提高至 200 毫秒。"
        ]
      }
    ],
    "repo": "packages/ui/src/Loading.tsx",
    "version": "1.9.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "1 week ago",
    "lastCommit": "c4b81fa",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "statistic",
    "name": "Statistic",
    "nameZh": "数据展示",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "gauge",
    "summary": "Single key metric with label, unit, and optional trend delta for KPI surfaces.",
    "summaryZh": "展示单个关键指标的组件，含标签、单位与可选趋势变化，适用于 KPI 区域。",
    "tags": [
      "kpi",
      "metric",
      "trend",
      "dashboard"
    ],
    "overview": "Use Statistic to surface one headline number on dashboards and overview panels — throughput, yield, uptime. Keep the value typographically dominant, set the unit in a muted color.text.secondary, and color trend deltas with semantic up/down tokens. Group several Statistics in a row but keep each focused on a single measure.",
    "overviewZh": "Statistic 用于在仪表盘与概览面板上突出单个核心数字，如产能、良率、在线时长。数值在排版上应占主导，单位使用较弱的 color.text.secondary，趋势变化用语义化的上升/下降令牌着色。可在一行中并列多个 Statistic，但每个只聚焦单一度量。",
    "dos": [
      "Keep the metric value the largest element and the label secondary.",
      "Show units and precision consistently across comparable statistics.",
      "Use semantic trend colors so increases and decreases read at a glance."
    ],
    "dosZh": [
      "让指标数值成为最大元素，标签作为次要信息。",
      "在可对比的统计项之间保持单位与精度一致。",
      "使用语义化趋势颜色，使涨跌一目了然。"
    ],
    "donts": [
      "Don't cram multiple metrics into one Statistic block.",
      "Don't imply a trend direction with color alone — pair it with an arrow.",
      "Don't show more decimal places than the measurement warrants."
    ],
    "dontsZh": [
      "不要在单个 Statistic 块中塞入多个指标。",
      "不要仅用颜色表达趋势方向——应同时配箭头。",
      "不要显示超出测量精度需要的小数位。"
    ],
    "examples": [
      {
        "id": "statistic-basic",
        "title": "Metric with unit",
        "titleZh": "带单位的指标",
        "note": "Value, label, and unit in a single block.",
        "noteZh": "在单个块中展示数值、标签与单位。",
        "show": true,
        "demo": "statistic-basic"
      },
      {
        "id": "statistic-trend",
        "title": "Metric with trend",
        "titleZh": "带趋势的指标",
        "note": "Headline value with a colored delta versus prior period.",
        "noteZh": "核心数值配以相对上期的彩色变化量。",
        "show": true,
        "demo": "statistic-trend"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "number | string",
        "def": "—",
        "required": true,
        "desc": "The headline metric value to display.",
        "descZh": "要展示的核心指标数值。"
      },
      {
        "name": "label",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Caption describing what the value represents.",
        "descZh": "说明该数值含义的标题文案。"
      },
      {
        "name": "unit",
        "type": "string",
        "def": "—",
        "required": false,
        "desc": "Unit suffix rendered in a muted style.",
        "descZh": "以弱化样式渲染的单位后缀。"
      },
      {
        "name": "trend",
        "type": "{ value: number; direction: 'up' | 'down' }",
        "def": "—",
        "required": false,
        "desc": "Delta versus a baseline, colored by direction.",
        "descZh": "相对基线的变化量，按方向着色。"
      },
      {
        "name": "precision",
        "type": "number",
        "def": "0",
        "required": false,
        "desc": "Number of decimal places for numeric values.",
        "descZh": "数值的小数位数。"
      }
    ],
    "changelog": [
      {
        "v": "1.5.0",
        "date": "2026-04-30",
        "notes": [
          "Added trend delta with semantic up/down coloring.",
          "Unit now uses color.text.secondary by default."
        ],
        "notesZh": [
          "新增带语义化涨跌着色的趋势变化量。",
          "单位默认改用 color.text.secondary。"
        ]
      }
    ],
    "repo": "packages/ui/src/Statistic.tsx",
    "version": "1.5.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "4 days ago",
    "lastCommit": "e90a157",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "steps",
    "name": "Steps",
    "nameZh": "步骤条",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "route",
    "summary": "Sequential progress indicator showing completed, active, and upcoming stages.",
    "summaryZh": "顺序进度指示器，展示已完成、进行中与待处理的阶段。",
    "tags": [
      "progress",
      "wizard",
      "sequence",
      "navigation"
    ],
    "overview": "Use Steps to communicate where a user is within a bounded, ordered process such as recipe setup or a calibration wizard. Mark the active step with accent.default, completed steps with a check, and upcoming steps with color.text.secondary. Prefer horizontal orientation for short flows and vertical when each step carries a description.",
    "overviewZh": "Steps 用于表明用户在有限且有序流程中的位置，例如配方设置或校准向导。当前步骤使用 accent.default 标记，已完成步骤显示对勾，待处理步骤使用 color.text.secondary。短流程优先横向排布，每步带描述时使用纵向。",
    "dos": [
      "Keep step labels short and action-oriented.",
      "Show completed steps with a check so progress is unambiguous.",
      "Use vertical orientation when steps need supporting descriptions."
    ],
    "dosZh": [
      "步骤标签应简短且以动作为导向。",
      "已完成步骤显示对勾，使进度清晰无歧义。",
      "当步骤需要辅助描述时使用纵向排布。"
    ],
    "donts": [
      "Don't use Steps for non-linear navigation between unrelated sections.",
      "Don't exceed about five steps horizontally before it crowds.",
      "Don't allow jumping to a future step that depends on earlier input."
    ],
    "dontsZh": [
      "不要将 Steps 用于无关板块之间的非线性导航。",
      "横向排布超过约五步会显得拥挤，应避免。",
      "不要允许跳转到依赖前序输入的后续步骤。"
    ],
    "examples": [
      {
        "id": "steps-horizontal",
        "title": "Horizontal steps",
        "titleZh": "横向步骤条",
        "note": "Three-stage flow with current step highlighted.",
        "noteZh": "三阶段流程，高亮当前步骤。",
        "show": true,
        "demo": "steps-horizontal"
      },
      {
        "id": "steps-vertical",
        "title": "Vertical with descriptions",
        "titleZh": "带描述的纵向步骤",
        "note": "Each step shows a supporting description line.",
        "noteZh": "每个步骤展示一行辅助描述。",
        "show": false,
        "demo": "steps-vertical"
      }
    ],
    "props": [
      {
        "name": "steps",
        "type": "{ label: string; description?: string }[]",
        "def": "—",
        "required": true,
        "desc": "Ordered step definitions with optional descriptions.",
        "descZh": "有序的步骤定义，可附描述。"
      },
      {
        "name": "current",
        "type": "number",
        "def": "0",
        "required": true,
        "desc": "Zero-based index of the active step.",
        "descZh": "当前步骤的从零开始索引。"
      },
      {
        "name": "orientation",
        "type": "'horizontal' | 'vertical'",
        "def": "'horizontal'",
        "required": false,
        "desc": "Layout direction of the step sequence.",
        "descZh": "步骤序列的排布方向。"
      },
      {
        "name": "status",
        "type": "'process' | 'error'",
        "def": "'process'",
        "required": false,
        "desc": "Visual state of the current step, e.g. error styling.",
        "descZh": "当前步骤的视觉状态，例如错误样式。"
      }
    ],
    "changelog": [
      {
        "v": "1.4.0",
        "date": "2026-03-22",
        "notes": [
          "Added error status for the current step.",
          "Vertical layout now supports per-step descriptions."
        ],
        "notesZh": [
          "为当前步骤新增 error 状态。",
          "纵向布局现支持逐步描述。"
        ]
      }
    ],
    "repo": "packages/ui/src/Steps.tsx",
    "version": "1.4.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "6 days ago",
    "lastCommit": "b17d3e4",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "timeline",
    "name": "Timeline",
    "nameZh": "时间轴",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "activity",
    "summary": "Vertical chronological list of events with markers, timestamps, and status colors.",
    "summaryZh": "纵向按时间排列的事件列表，含节点标记、时间戳与状态颜色。",
    "tags": [
      "chronology",
      "events",
      "history",
      "audit"
    ],
    "overview": "Use Timeline for ordered event histories such as alarm sequences, audit logs, and run-step traces. Color markers with semantic status tokens and keep timestamps in color.text.secondary so the event content stays primary. For very long histories, lazy-load older entries rather than rendering the entire log at once.",
    "overviewZh": "Timeline 用于有序的事件历史，例如报警序列、审计日志与运行步骤追踪。节点标记使用语义化状态令牌着色，时间戳使用 color.text.secondary，让事件内容保持主导。对于很长的历史记录，应惰性加载更早条目，而非一次性渲染整段日志。",
    "dos": [
      "Order events newest-first or oldest-first consistently within a view.",
      "Use semantic colors on markers to convey event severity.",
      "Lazy-load older entries for long histories."
    ],
    "dosZh": [
      "在同一视图内统一采用最新在前或最早在前的排序。",
      "在节点标记上使用语义化颜色传达事件严重程度。",
      "对长历史记录惰性加载更早条目。"
    ],
    "donts": [
      "Don't bury the timestamp; keep it readable but secondary.",
      "Don't use Timeline for parallel, non-sequential data.",
      "Don't render thousands of events without windowing."
    ],
    "dontsZh": [
      "不要埋没时间戳；应保持可读但作为次要信息。",
      "不要将 Timeline 用于并行、非顺序的数据。",
      "不要在无窗口化的情况下渲染成千上万条事件。"
    ],
    "examples": [
      {
        "id": "timeline-basic",
        "title": "Event timeline",
        "titleZh": "事件时间轴",
        "note": "Vertical events with timestamps and colored markers.",
        "noteZh": "纵向事件，含时间戳与彩色节点标记。",
        "show": true,
        "demo": "timeline-basic"
      },
      {
        "id": "timeline-status",
        "title": "Status markers",
        "titleZh": "状态节点",
        "note": "Markers colored by event severity.",
        "noteZh": "按事件严重程度着色的节点。",
        "show": true,
        "demo": "timeline-status"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "TimelineItem[]",
        "def": "—",
        "required": true,
        "desc": "Event entries with content, timestamp, and status.",
        "descZh": "事件条目，含内容、时间戳与状态。"
      },
      {
        "name": "order",
        "type": "'asc' | 'desc'",
        "def": "'desc'",
        "required": false,
        "desc": "Chronological order; desc shows newest events first.",
        "descZh": "时间顺序；desc 表示最新事件在前。"
      },
      {
        "name": "showTime",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Toggles display of per-event timestamps.",
        "descZh": "切换是否显示每条事件的时间戳。"
      },
      {
        "name": "compact",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Reduces vertical spacing for dense logs.",
        "descZh": "为密集日志缩小纵向间距。"
      }
    ],
    "changelog": [
      {
        "v": "1.3.1",
        "date": "2026-02-27",
        "notes": [
          "Added compact mode for dense audit logs.",
          "Marker colors mapped to semantic status tokens."
        ],
        "notesZh": [
          "为密集审计日志新增 compact 模式。",
          "节点颜色映射到语义化状态令牌。"
        ]
      }
    ],
    "repo": "packages/ui/src/Timeline.tsx",
    "version": "1.3.1",
    "lastEditBy": "m.okafor",
    "lastEditAt": "1 week ago",
    "lastCommit": "f6a4d09",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "collapse",
    "name": "Collapse",
    "nameZh": "折叠面板",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "chevronD",
    "summary": "Expandable panels that show or hide grouped content to manage density.",
    "summaryZh": "可展开/收起的面板，用于显示或隐藏分组内容以控制信息密度。",
    "tags": [
      "accordion",
      "disclosure",
      "expandable",
      "density"
    ],
    "overview": "Use Collapse to tuck away secondary or advanced content — parameter groups, optional settings, detail sections — so the default view stays scannable. Indicate state with a chevron that rotates on expand and use spacing.inset.md for panel padding. Use accordion mode when only one section should be open at a time.",
    "overviewZh": "Collapse 用于收纳次要或进阶内容——参数组、可选设置、详情区块——使默认视图保持易扫读。用展开时旋转的箭头指示状态，面板内边距使用 spacing.inset.md。当同一时间只应展开一个区块时使用手风琴模式。",
    "dos": [
      "Show a chevron that rotates to communicate open and closed states.",
      "Use accordion mode when only one panel should stay open.",
      "Keep panel headers descriptive so collapsed content is discoverable."
    ],
    "dosZh": [
      "显示一个旋转的箭头来表达展开与收起状态。",
      "当只应保持一个面板展开时使用手风琴模式。",
      "面板标题应具描述性，使收起的内容易于被发现。"
    ],
    "donts": [
      "Don't hide critical, must-see information behind a collapse.",
      "Don't nest collapses more than one level deep.",
      "Don't animate height without respecting reduced-motion settings."
    ],
    "dontsZh": [
      "不要将关键的、必须看到的信息隐藏在折叠面板之后。",
      "不要将折叠面板嵌套超过一层。",
      "不要在不遵循减弱动效设置的情况下做高度动画。"
    ],
    "examples": [
      {
        "id": "collapse-basic",
        "title": "Single panel",
        "titleZh": "单个面板",
        "note": "One expandable section with a rotating chevron.",
        "noteZh": "一个可展开区块，配旋转箭头。",
        "show": true,
        "demo": "collapse-basic"
      },
      {
        "id": "collapse-accordion",
        "title": "Accordion group",
        "titleZh": "手风琴组",
        "note": "Multiple panels where only one stays open.",
        "noteZh": "多个面板，仅保持一个展开。",
        "show": true,
        "demo": "collapse-accordion"
      }
    ],
    "props": [
      {
        "name": "items",
        "type": "{ key: string; header: string; content: ReactNode }[]",
        "def": "—",
        "required": true,
        "desc": "Panel definitions with header and body content.",
        "descZh": "面板定义，含标题与正文内容。"
      },
      {
        "name": "accordion",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "When true, opening one panel closes the others.",
        "descZh": "为 true 时，展开一个面板会收起其他面板。"
      },
      {
        "name": "defaultOpen",
        "type": "string[]",
        "def": "[]",
        "required": false,
        "desc": "Keys of panels expanded on first render.",
        "descZh": "首次渲染时展开的面板 key 列表。"
      },
      {
        "name": "onChange",
        "type": "(openKeys: string[]) => void",
        "def": "—",
        "required": false,
        "desc": "Fires when the set of open panels changes.",
        "descZh": "当展开面板的集合变化时触发。"
      }
    ],
    "changelog": [
      {
        "v": "1.2.0",
        "date": "2026-01-29",
        "notes": [
          "Added accordion mode.",
          "Height animation now honors prefers-reduced-motion."
        ],
        "notesZh": [
          "新增手风琴模式。",
          "高度动画现遵循 prefers-reduced-motion。"
        ]
      }
    ],
    "repo": "packages/ui/src/Collapse.tsx",
    "version": "1.2.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "2 weeks ago",
    "lastCommit": "1ac58d2",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "pageheader",
    "name": "PageHeader",
    "nameZh": "页头",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "layers",
    "summary": "Top-of-page region with title, breadcrumb, metadata, and primary actions.",
    "summaryZh": "页面顶部区域，含标题、面包屑、元信息与主要操作。",
    "tags": [
      "header",
      "title",
      "breadcrumb",
      "actions"
    ],
    "overview": "Use PageHeader to orient users at the top of a view with a clear title, optional breadcrumb, and the page's primary actions aligned right. Keep one dominant action and demote the rest, and separate the header from content with color.border.default. Reserve the back affordance for true sub-pages within a navigation hierarchy.",
    "overviewZh": "PageHeader 用于在视图顶部为用户提供方位，含清晰标题、可选面包屑，以及右对齐的页面主要操作。只保留一个主导操作，其余降级处理，并用 color.border.default 将页头与内容分隔。返回入口仅用于导航层级中真正的子页面。",
    "dos": [
      "Keep a single primary action and present secondary actions as subtle.",
      "Show a breadcrumb only when the page sits inside a real hierarchy.",
      "Align actions to the right and the title to the left for scannability."
    ],
    "dosZh": [
      "只保留一个主操作，次要操作以低调样式呈现。",
      "仅当页面处于真实层级中时才显示面包屑。",
      "操作右对齐、标题左对齐，便于扫读。"
    ],
    "donts": [
      "Don't crowd the header with more than two prominent actions.",
      "Don't show a back arrow on top-level pages.",
      "Don't duplicate the page title inside the body content."
    ],
    "dontsZh": [
      "不要在页头堆放超过两个显著操作。",
      "不要在顶层页面显示返回箭头。",
      "不要在正文内容中重复页面标题。"
    ],
    "examples": [
      {
        "id": "pageheader-basic",
        "title": "Title with actions",
        "titleZh": "带操作的标题",
        "note": "Title on the left, primary action on the right.",
        "noteZh": "标题在左，主操作在右。",
        "show": true,
        "demo": "pageheader-basic"
      },
      {
        "id": "pageheader-breadcrumb",
        "title": "With breadcrumb",
        "titleZh": "带面包屑",
        "note": "Sub-page header with breadcrumb and back affordance.",
        "noteZh": "带面包屑与返回入口的子页面页头。",
        "show": false,
        "demo": "pageheader-breadcrumb"
      }
    ],
    "props": [
      {
        "name": "title",
        "type": "string",
        "def": "—",
        "required": true,
        "desc": "Primary page title rendered as the heading.",
        "descZh": "作为标题渲染的主要页面名称。"
      },
      {
        "name": "breadcrumb",
        "type": "{ label: string; href?: string }[]",
        "def": "—",
        "required": false,
        "desc": "Hierarchy trail shown above the title.",
        "descZh": "显示在标题上方的层级路径。"
      },
      {
        "name": "actions",
        "type": "ReactNode",
        "def": "—",
        "required": false,
        "desc": "Right-aligned action controls, typically buttons.",
        "descZh": "右对齐的操作控件，通常为按钮。"
      },
      {
        "name": "onBack",
        "type": "() => void",
        "def": "—",
        "required": false,
        "desc": "When set, renders a back affordance for sub-pages.",
        "descZh": "设置后，为子页面渲染返回入口。"
      }
    ],
    "changelog": [
      {
        "v": "1.6.0",
        "date": "2026-04-11",
        "notes": [
          "Added breadcrumb slot above the title.",
          "Actions area now wraps gracefully on narrow viewports."
        ],
        "notesZh": [
          "在标题上方新增面包屑槽位。",
          "操作区现可在窄视口下优雅换行。"
        ]
      }
    ],
    "repo": "packages/ui/src/PageHeader.tsx",
    "version": "1.6.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "3 days ago",
    "lastCommit": "9b0c6e3",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "infinitescroll",
    "name": "InfiniteScroll",
    "nameZh": "无限滚动",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "beta",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "refresh",
    "summary": "Loads additional content automatically as the user nears the end of a list.",
    "summaryZh": "当用户接近列表底部时自动加载更多内容。",
    "tags": [
      "pagination",
      "lazy-load",
      "list",
      "feed"
    ],
    "overview": "Use InfiniteScroll for open-ended feeds and large lists where page-by-page controls add friction, such as event streams and search results. Trigger the next fetch from an intersection sentinel near the bottom and show a Loading indicator while fetching. Avoid it for content users need to bookmark or compare across pages — prefer explicit pagination there.",
    "overviewZh": "InfiniteScroll 适用于无明确终点的信息流与大型列表，逐页控件会带来摩擦的场景，例如事件流与搜索结果。通过底部附近的交叉观察哨兵触发下一次加载，并在请求期间显示 Loading 指示器。对于用户需要收藏或跨页对比的内容应避免使用——那种情况应优先显式分页。",
    "dos": [
      "Place the load sentinel a screen-height before the end to prefetch smoothly.",
      "Show a Loading indicator and a clear end-of-list marker.",
      "Preserve scroll position when new items append above the fold."
    ],
    "dosZh": [
      "将加载哨兵放在距底部约一屏处，以平滑预取。",
      "显示 Loading 指示器与清晰的列表末尾标记。",
      "当新条目在可视区上方追加时保持滚动位置。"
    ],
    "donts": [
      "Don't use it where footers or deep pagination are essential.",
      "Don't fire overlapping fetches; guard with a loading flag.",
      "Don't lose the user's place when content reflows."
    ],
    "dontsZh": [
      "不要在页脚或深度分页必不可少的场景使用。",
      "不要触发重叠的加载请求；用加载标志位防护。",
      "不要在内容重排时丢失用户的浏览位置。"
    ],
    "examples": [
      {
        "id": "infinitescroll-basic",
        "title": "Auto-loading feed",
        "titleZh": "自动加载信息流",
        "note": "Appends pages as the sentinel enters the viewport.",
        "noteZh": "当哨兵进入视口时追加新页。",
        "show": true,
        "demo": "infinitescroll-basic"
      }
    ],
    "props": [
      {
        "name": "loadMore",
        "type": "() => Promise<void>",
        "def": "—",
        "required": true,
        "desc": "Callback to fetch the next batch of items.",
        "descZh": "用于获取下一批条目的回调。"
      },
      {
        "name": "hasMore",
        "type": "boolean",
        "def": "true",
        "required": true,
        "desc": "Whether more items remain to be loaded.",
        "descZh": "是否还有更多条目可加载。"
      },
      {
        "name": "threshold",
        "type": "number",
        "def": "300",
        "required": false,
        "desc": "Pixel distance from the end that triggers a load.",
        "descZh": "触发加载的距底部像素距离。"
      },
      {
        "name": "loader",
        "type": "ReactNode",
        "def": "—",
        "required": false,
        "desc": "Custom indicator shown while fetching the next batch.",
        "descZh": "获取下一批时显示的自定义指示器。"
      },
      {
        "name": "endMessage",
        "type": "ReactNode",
        "def": "—",
        "required": false,
        "desc": "Content shown when no more items remain.",
        "descZh": "无更多条目时显示的内容。"
      }
    ],
    "changelog": [
      {
        "v": "0.4.0",
        "date": "2026-05-20",
        "notes": [
          "Switched trigger to IntersectionObserver sentinel.",
          "Added endMessage slot."
        ],
        "notesZh": [
          "改用 IntersectionObserver 哨兵触发。",
          "新增 endMessage 槽位。"
        ]
      },
      {
        "v": "0.3.0",
        "date": "2026-04-02",
        "notes": [
          "Initial beta release."
        ],
        "notesZh": [
          "首个 beta 版本发布。"
        ]
      }
    ],
    "repo": "packages/ui/src/InfiniteScroll.tsx",
    "version": "0.4.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "yesterday",
    "lastCommit": "5e2af71",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "drawer",
    "name": "Drawer",
    "nameZh": "抽屉",
    "category": "Data display",
    "categoryZh": "展示",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "layers",
    "summary": "Edge-anchored sliding panel for secondary detail and side workflows without leaving the page.",
    "summaryZh": "贴边滑出的面板，用于在不离开页面的情况下展示次级详情与侧边工作流。",
    "tags": [
      "overlay",
      "panel",
      "detail",
      "side"
    ],
    "overview": "Use Drawer for secondary detail, filters, or side tasks where preserving the underlying context matters more than full interruption — pairing well with Table row inspection. Anchor it to an edge, size it for content, and use color.overlay.scrim for the optional backdrop. Choose Drawer over Modal when users may reference the page behind it.",
    "overviewZh": "Drawer 用于次级详情、筛选或侧边任务，在保留底层上下文比完全打断更重要的场景——与 Table 行详情查看搭配尤佳。将其贴边锚定，按内容确定尺寸，可选背景使用 color.overlay.scrim。当用户可能需要参照其后页面时，应选择 Drawer 而非 Modal。",
    "dos": [
      "Anchor consistently to the same edge for a given task type.",
      "Use a Drawer when users benefit from seeing the page behind it.",
      "Let Esc and scrim click close it for non-blocking workflows."
    ],
    "dosZh": [
      "同类任务始终锚定在相同边缘。",
      "当用户需要看到其后页面时使用 Drawer。",
      "对非阻塞工作流允许 Esc 与点击遮罩关闭。"
    ],
    "donts": [
      "Don't use a Drawer for hard confirmations — that's a Modal's job.",
      "Don't make the drawer wider than the content needs.",
      "Don't open multiple drawers from different edges at once."
    ],
    "dontsZh": [
      "不要用 Drawer 做强确认——那是 Modal 的职责。",
      "不要让抽屉超出内容所需的宽度。",
      "不要同时从不同边缘打开多个抽屉。"
    ],
    "examples": [
      {
        "id": "drawer-right",
        "title": "Right-side detail",
        "titleZh": "右侧详情",
        "note": "Row detail sliding in from the right edge.",
        "noteZh": "行详情从右侧边缘滑入。",
        "show": true,
        "demo": "drawer-right"
      },
      {
        "id": "drawer-filters",
        "title": "Filter panel",
        "titleZh": "筛选面板",
        "note": "Left drawer holding list filters.",
        "noteZh": "承载列表筛选项的左侧抽屉。",
        "show": false,
        "demo": "drawer-filters"
      }
    ],
    "props": [
      {
        "name": "open",
        "type": "boolean",
        "def": "false",
        "required": true,
        "desc": "Controls visibility of the drawer panel.",
        "descZh": "控制抽屉面板的显隐。"
      },
      {
        "name": "onClose",
        "type": "() => void",
        "def": "—",
        "required": true,
        "desc": "Called when the drawer is dismissed.",
        "descZh": "抽屉被关闭时触发。"
      },
      {
        "name": "anchor",
        "type": "'left' | 'right' | 'top' | 'bottom'",
        "def": "'right'",
        "required": false,
        "desc": "Edge the drawer slides in from.",
        "descZh": "抽屉滑入的边缘方向。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md' | 'lg' | number",
        "def": "'md'",
        "required": false,
        "desc": "Width or height preset, or an explicit pixel value.",
        "descZh": "宽度或高度预设，或明确的像素值。"
      },
      {
        "name": "scrim",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Whether to render a dimming backdrop behind the panel.",
        "descZh": "是否在面板后渲染变暗的背景遮罩。"
      }
    ],
    "changelog": [
      {
        "v": "2.1.0",
        "date": "2026-03-05",
        "notes": [
          "Added top and bottom anchors.",
          "Scrim can now be disabled for non-blocking side tasks."
        ],
        "notesZh": [
          "新增顶部与底部锚定方向。",
          "现可为非阻塞侧边任务禁用遮罩。"
        ]
      }
    ],
    "repo": "packages/ui/src/Drawer.tsx",
    "version": "2.1.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "5 days ago",
    "lastCommit": "d8f3b60",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "progress",
    "name": "Progress",
    "nameZh": "进度条",
    "category": "Feedback",
    "categoryZh": "反馈",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "gauge",
    "summary": "Communicates the completion state of an ongoing task as a linear bar or indeterminate track.",
    "summaryZh": "以线性进度条或不确定状态轨道传达进行中任务的完成情况。",
    "tags": [
      "feedback",
      "loading",
      "status"
    ],
    "overview": "Progress shows how far along a determinate task is, or signals indeterminate activity when the duration is unknown. The fill uses accent.default and the track uses color.border.default so it reads consistently across all four brand themes. Prefer determinate mode whenever you can compute a percentage; reserve the indeterminate variant for waits under a few seconds.",
    "overviewZh": "进度条用于展示确定性任务的完成程度,或在时长未知时以不确定状态提示正在处理。填充色取自 accent.default,轨道取自 color.border.default,从而在四套品牌主题下保持一致观感。只要能计算百分比就优先使用确定模式,不确定变体仅用于数秒以内的等待。",
    "dos": [
      "Use determinate mode when a real percentage can be computed.",
      "Pair the bar with a numeric or textual readout for long operations.",
      "Map error states to the danger status token rather than hiding the bar."
    ],
    "dosZh": [
      "能够计算真实百分比时使用确定模式。",
      "长耗时操作中为进度条配上数字或文字说明。",
      "出错状态映射到 danger 状态令牌,而非直接隐藏进度条。"
    ],
    "donts": [
      "Animate an indeterminate bar for multi-minute jobs — use a status panel.",
      "Snap the fill backwards once it has advanced.",
      "Stack multiple progress bars for sub-steps of one task."
    ],
    "dontsZh": [
      "不要为耗时数分钟的任务使用不确定动画,应改用状态面板。",
      "进度推进后不要让填充回退。",
      "不要为同一任务的多个子步骤堆叠多条进度条。"
    ],
    "examples": [
      {
        "id": "progress-determinate",
        "title": "Determinate",
        "titleZh": "确定进度",
        "note": "Fill width driven by value; uses accent.default.",
        "noteZh": "填充宽度由 value 驱动,取色 accent.default。",
        "show": true,
        "demo": "progress-determinate"
      },
      {
        "id": "progress-indeterminate",
        "title": "Indeterminate",
        "titleZh": "不确定进度",
        "note": "Looping track for unknown-duration waits.",
        "noteZh": "时长未知的等待使用循环轨道。",
        "show": true,
        "demo": "progress-indeterminate"
      },
      {
        "id": "progress-labeled",
        "title": "With label",
        "titleZh": "带标签",
        "note": "Percentage readout paired with the bar.",
        "noteZh": "进度条搭配百分比读数。",
        "show": false,
        "demo": "progress-labeled"
      }
    ],
    "props": [
      {
        "name": "value",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Current value (0–100). Omit for indeterminate.",
        "descZh": "当前值(0–100)。不传则为不确定状态。"
      },
      {
        "name": "max",
        "type": "number",
        "def": "100",
        "required": false,
        "desc": "Upper bound of the range.",
        "descZh": "取值范围上限。"
      },
      {
        "name": "indeterminate",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Show a looping track when duration is unknown.",
        "descZh": "时长未知时显示循环轨道。"
      },
      {
        "name": "status",
        "type": "'default' | 'success' | 'danger'",
        "def": "'default'",
        "required": false,
        "desc": "Maps the fill to a status color token.",
        "descZh": "将填充色映射到对应状态令牌。"
      },
      {
        "name": "size",
        "type": "'sm' | 'md'",
        "def": "'md'",
        "required": false,
        "desc": "Track thickness.",
        "descZh": "轨道粗细。"
      },
      {
        "name": "showValue",
        "type": "boolean",
        "def": "false",
        "required": false,
        "desc": "Render a percentage readout.",
        "descZh": "是否渲染百分比读数。"
      }
    ],
    "changelog": [
      {
        "v": "1.5.0",
        "date": "2026-05-27",
        "notes": [
          "Added `status` prop mapping fill to success/danger tokens.",
          "Indeterminate track now references `color.border.default`."
        ],
        "notesZh": [
          "新增 `status` 属性,将填充映射到 success/danger 令牌。",
          "不确定轨道改为引用 `color.border.default`。"
        ]
      },
      {
        "v": "1.4.1",
        "date": "2026-04-19",
        "notes": [
          "Fixed fill easing so it no longer snaps backwards."
        ],
        "notesZh": [
          "修复填充缓动,不再出现进度回退。"
        ]
      }
    ],
    "repo": "packages/ui/src/Progress.tsx",
    "version": "1.5.0",
    "lastEditBy": "p.narang",
    "lastEditAt": "3 days ago",
    "lastCommit": "c4d8e10",
    "hasDraft": false,
    "wired": true
  },
  {
    "id": "message",
    "name": "Message",
    "nameZh": "信息反馈",
    "category": "Feedback",
    "categoryZh": "反馈",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "bell",
    "summary": "Transient toast that confirms an action or reports a result without interrupting flow.",
    "summaryZh": "短暂出现的轻量提示,用于确认操作或反馈结果,且不打断用户当前流程。",
    "tags": [
      "feedback",
      "toast",
      "notification"
    ],
    "overview": "Message is a lightweight, auto-dismissing toast for confirming success, surfacing recoverable errors, or noting background results. Severity maps to status tokens — success uses color.status.success and errors use color.status.danger — while the surface uses radius.control and spacing.inset.md. Reserve Message for transient feedback; use Alert banner for conditions that must persist until acknowledged.",
    "overviewZh": "信息反馈是一种轻量、可自动消失的提示,用于确认成功、提示可恢复的错误或告知后台结果。严重级别映射到状态令牌——成功使用 color.status.success,错误使用 color.status.danger;容器则采用 radius.control 与 spacing.inset.md。信息反馈仅用于短暂反馈,需持续到用户确认的情况请使用 Alert 横幅。",
    "dos": [
      "Keep the message to one short line of plain language.",
      "Map severity to the matching status token.",
      "Auto-dismiss success messages after a few seconds."
    ],
    "dosZh": [
      "保持信息为一行简洁的口语化文字。",
      "将严重级别映射到对应的状态令牌。",
      "成功提示在数秒后自动消失。"
    ],
    "donts": [
      "Use a toast for errors the user must act on — use a banner.",
      "Queue more than a few messages at once.",
      "Put critical, non-recoverable failures in a transient toast."
    ],
    "dontsZh": [
      "不要用提示承载需要用户处理的错误,应改用横幅。",
      "不要一次性堆叠过多提示。",
      "不要将严重、不可恢复的故障放进短暂提示中。"
    ],
    "examples": [
      {
        "id": "message-success",
        "title": "Success",
        "titleZh": "成功",
        "note": "Confirms a completed action; uses color.status.success.",
        "noteZh": "确认操作完成,取色 color.status.success。",
        "show": true,
        "demo": "message-success"
      },
      {
        "id": "message-error",
        "title": "Error",
        "titleZh": "错误",
        "note": "Reports a recoverable failure; uses color.status.danger.",
        "noteZh": "反馈可恢复的失败,取色 color.status.danger。",
        "show": true,
        "demo": "message-error"
      },
      {
        "id": "message-action",
        "title": "With action",
        "titleZh": "带操作",
        "note": "Adds an Undo affordance to a confirmation.",
        "noteZh": "在确认提示上加入撤销操作。",
        "show": false,
        "demo": "message-action"
      }
    ],
    "props": [
      {
        "name": "severity",
        "type": "'info' | 'success' | 'warning' | 'error'",
        "def": "'info'",
        "required": false,
        "desc": "Status level driving icon and color.",
        "descZh": "决定图标与颜色的状态级别。"
      },
      {
        "name": "content",
        "type": "ReactNode",
        "def": "—",
        "required": true,
        "desc": "Message body text.",
        "descZh": "提示正文内容。"
      },
      {
        "name": "duration",
        "type": "number",
        "def": "4000",
        "required": false,
        "desc": "Auto-dismiss delay in ms; 0 keeps it open.",
        "descZh": "自动消失延时(毫秒);为 0 时不自动消失。"
      },
      {
        "name": "action",
        "type": "ReactNode",
        "def": "—",
        "required": false,
        "desc": "Optional action slot, e.g. Undo.",
        "descZh": "可选操作槽位,例如撤销。"
      },
      {
        "name": "onClose",
        "type": "() => void",
        "def": "—",
        "required": false,
        "desc": "Called when the message dismisses.",
        "descZh": "提示消失时触发的回调。"
      }
    ],
    "changelog": [
      {
        "v": "2.1.0",
        "date": "2026-05-30",
        "notes": [
          "Added `action` slot for inline Undo.",
          "Severity colors now reference `color.status.*` tokens."
        ],
        "notesZh": [
          "新增 `action` 槽位以支持行内撤销。",
          "严重级别颜色改为引用 `color.status.*` 令牌。"
        ]
      },
      {
        "v": "2.0.0",
        "date": "2026-03-22",
        "notes": [
          "Rewrote as an imperative toast queue API."
        ],
        "notesZh": [
          "重构为命令式的提示队列 API。"
        ]
      }
    ],
    "repo": "packages/ui/src/Message.tsx",
    "version": "2.1.0",
    "lastEditBy": "m.okafor",
    "lastEditAt": "2 days ago",
    "lastCommit": "b71f3a9",
    "hasDraft": true,
    "wired": false
  },
  {
    "id": "popover",
    "name": "Popover",
    "nameZh": "气泡",
    "category": "Feedback",
    "categoryZh": "反馈",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "component",
    "summary": "Floating panel anchored to a trigger that reveals rich, contextual content on demand.",
    "summaryZh": "锚定在触发元素上的浮层面板,按需展示丰富的上下文内容。",
    "tags": [
      "feedback",
      "overlay",
      "contextual"
    ],
    "overview": "Popover anchors a floating surface to a trigger to present rich content — help text, a small form, or a menu — without leaving the current view. The panel uses radius.control, spacing.inset.md, and a hairline from color.border.default, and it flips placement automatically to stay in the viewport. Use Popover for interactive content; for a plain text hint on hover, use a lighter tooltip instead.",
    "overviewZh": "气泡将一个浮层锚定到触发元素上,在不离开当前视图的前提下展示丰富内容——帮助说明、小型表单或菜单。面板采用 radius.control、spacing.inset.md,并以 color.border.default 描出细边,且会自动翻转位置以保持在可视区域内。气泡用于可交互内容;仅在悬停时显示纯文本提示请改用更轻量的 tooltip。",
    "dos": [
      "Anchor the popover to the element that triggered it.",
      "Let placement flip automatically to stay within the viewport.",
      "Dismiss on outside click and on Escape."
    ],
    "dosZh": [
      "将气泡锚定到触发它的元素上。",
      "允许位置自动翻转以保持在可视区域内。",
      "点击外部或按 Escape 时关闭。"
    ],
    "donts": [
      "Nest a popover inside another popover.",
      "Put a destructive action behind a hover-only trigger.",
      "Fill a popover with long-form content — use a panel or modal."
    ],
    "dontsZh": [
      "不要在气泡内嵌套另一个气泡。",
      "不要把破坏性操作放在仅悬停触发的气泡里。",
      "不要在气泡里塞入长篇内容,应改用面板或弹窗。"
    ],
    "examples": [
      {
        "id": "popover-basic",
        "title": "Basic popover",
        "titleZh": "基础气泡",
        "note": "Anchored panel with hairline from color.border.default.",
        "noteZh": "锚定面板,细边取自 color.border.default。",
        "show": true,
        "demo": "popover-basic"
      },
      {
        "id": "popover-placement",
        "title": "Placement",
        "titleZh": "位置",
        "note": "Auto-flips to top/bottom/start/end to stay in view.",
        "noteZh": "自动翻转到上/下/前/后以保持可见。",
        "show": true,
        "demo": "popover-placement"
      },
      {
        "id": "popover-form",
        "title": "With form",
        "titleZh": "内嵌表单",
        "note": "Compact inline form inside the panel.",
        "noteZh": "面板内的紧凑行内表单。",
        "show": false,
        "demo": "popover-form"
      }
    ],
    "props": [
      {
        "name": "trigger",
        "type": "ReactNode",
        "def": "—",
        "required": true,
        "desc": "Element the popover anchors to.",
        "descZh": "气泡所锚定的元素。"
      },
      {
        "name": "placement",
        "type": "'top' | 'bottom' | 'start' | 'end'",
        "def": "'bottom'",
        "required": false,
        "desc": "Preferred side; auto-flips to fit.",
        "descZh": "首选展开方向,会自动翻转以适配。"
      },
      {
        "name": "open",
        "type": "boolean",
        "def": "—",
        "required": false,
        "desc": "Controlled open state.",
        "descZh": "受控的展开状态。"
      },
      {
        "name": "onOpenChange",
        "type": "(open: boolean) => void",
        "def": "—",
        "required": false,
        "desc": "Open-state change handler.",
        "descZh": "展开状态变化的回调。"
      },
      {
        "name": "dismissOnOutsideClick",
        "type": "boolean",
        "def": "true",
        "required": false,
        "desc": "Close when clicking outside.",
        "descZh": "点击外部时是否关闭。"
      },
      {
        "name": "children",
        "type": "ReactNode",
        "def": "—",
        "required": true,
        "desc": "Popover panel content.",
        "descZh": "气泡面板内容。"
      }
    ],
    "changelog": [
      {
        "v": "1.7.0",
        "date": "2026-05-15",
        "notes": [
          "Placement now auto-flips to stay within the viewport.",
          "Panel border references `color.border.default`."
        ],
        "notesZh": [
          "位置现可自动翻转以保持在可视区域内。",
          "面板边框改为引用 `color.border.default`。"
        ]
      },
      {
        "v": "1.6.0",
        "date": "2026-04-04",
        "notes": [
          "Added controlled `open` / `onOpenChange` API."
        ],
        "notesZh": [
          "新增受控的 `open` / `onOpenChange` 接口。"
        ]
      }
    ],
    "repo": "packages/ui/src/Popover.tsx",
    "version": "1.7.0",
    "lastEditBy": "lin.zhang",
    "lastEditAt": "6 days ago",
    "lastCommit": "d92a4f1",
    "hasDraft": false,
    "wired": false
  },
  {
    "id": "badge",
    "name": "Badge",
    "nameZh": "标记",
    "category": "Feedback",
    "categoryZh": "反馈",
    "status": "stable",
    "caution": false,
    "cautionReason": "",
    "cautionReasonZh": "",
    "icon": "tag",
    "summary": "Compact label that annotates an element with a status, count, or category.",
    "summaryZh": "用于为元素标注状态、数量或分类的紧凑标签。",
    "tags": [
      "feedback",
      "status",
      "label"
    ],
    "overview": "Badge attaches a small, glanceable label to another element — a status pill, an unread count, or a category tag. Tone maps to status tokens so a danger badge stays consistent with other danger surfaces, and the shape uses radius.pill with spacing.inset.sm. Keep the text to one or two words or a number; for richer status messaging use an Alert banner.",
    "overviewZh": "标记为其他元素附加一个小巧、可一眼识别的标签——状态徽标、未读数量或分类标签。色调映射到状态令牌,使 danger 标记与其他 danger 表面保持一致;形状采用 radius.pill 与 spacing.inset.sm。文字应控制在一两个词或一个数字以内;需要更丰富的状态信息请使用 Alert 横幅。",
    "dos": [
      "Map tone to the matching status token.",
      "Keep badge text to one or two words or a count.",
      "Cap large counts (e.g. show 99+) to preserve layout."
    ],
    "dosZh": [
      "将色调映射到对应的状态令牌。",
      "标记文字控制在一两个词或一个数字以内。",
      "为较大计数封顶(如显示 99+)以维持布局。"
    ],
    "donts": [
      "Pack a sentence into a badge — use an Alert banner.",
      "Use color alone to convey meaning; pair with text or icon.",
      "Scatter many badges on one element."
    ],
    "dontsZh": [
      "不要把整句话塞进标记,应改用 Alert 横幅。",
      "不要仅靠颜色传达含义,需搭配文字或图标。",
      "不要在同一元素上散布过多标记。"
    ],
    "examples": [
      {
        "id": "badge-tones",
        "title": "Tones",
        "titleZh": "色调",
        "note": "Neutral, success, warning and danger map to status tokens.",
        "noteZh": "中性、成功、警告、危险四种色调映射到状态令牌。",
        "show": true,
        "demo": "badge-tones"
      },
      {
        "id": "badge-count",
        "title": "Count",
        "titleZh": "计数",
        "note": "Numeric badge with a 99+ overflow cap.",
        "noteZh": "数字标记,超出时封顶为 99+。",
        "show": true,
        "demo": "badge-count"
      },
      {
        "id": "badge-dot",
        "title": "Dot",
        "titleZh": "圆点",
        "note": "Minimal dot variant for presence/status.",
        "noteZh": "极简圆点变体,用于在线/状态指示。",
        "show": false,
        "demo": "badge-dot"
      }
    ],
    "props": [
      {
        "name": "tone",
        "type": "'neutral' | 'success' | 'warning' | 'danger'",
        "def": "'neutral'",
        "required": false,
        "desc": "Status color of the badge.",
        "descZh": "标记的状态颜色。"
      },
      {
        "name": "variant",
        "type": "'solid' | 'subtle' | 'dot'",
        "def": "'subtle'",
        "required": false,
        "desc": "Fill style of the badge.",
        "descZh": "标记的填充样式。"
      },
      {
        "name": "count",
        "type": "number",
        "def": "—",
        "required": false,
        "desc": "Numeric value; capped by `max`.",
        "descZh": "数字值,受 `max` 封顶限制。"
      },
      {
        "name": "max",
        "type": "number",
        "def": "99",
        "required": false,
        "desc": "Overflow cap for count (shows N+).",
        "descZh": "计数溢出上限(显示为 N+)。"
      },
      {
        "name": "children",
        "type": "ReactNode",
        "def": "—",
        "required": false,
        "desc": "Badge label text.",
        "descZh": "标记标签文字。"
      }
    ],
    "changelog": [
      {
        "v": "1.3.0",
        "date": "2026-05-11",
        "notes": [
          "Added `dot` variant for presence indicators.",
          "Tones now reference `color.status.*` tokens."
        ],
        "notesZh": [
          "新增用于在线指示的 `dot` 变体。",
          "色调改为引用 `color.status.*` 令牌。"
        ]
      },
      {
        "v": "1.2.0",
        "date": "2026-04-01",
        "notes": [
          "Added `count` with `max` overflow cap."
        ],
        "notesZh": [
          "新增 `count`,并支持 `max` 溢出封顶。"
        ]
      }
    ],
    "repo": "packages/ui/src/Badge.tsx",
    "version": "1.3.0",
    "lastEditBy": "j.reyes",
    "lastEditAt": "4 days ago",
    "lastCommit": "6e0b8c3",
    "hasDraft": true,
    "wired": true
  }
];

const COMPONENT_MAP = Object.fromEntries(COMPONENTS.map(c => [c.id, c]));

/* tokens a component consumes — derived from component-layer tokens by prefix. Read-only. */
function tokensUsedBy(componentId) {
  return TOKENS.filter(t => t.layer === 'component' && t.id.split('.')[0] === componentId);
}

const COMP_STATUS = {
  stable:     { label: 'Stable',     labelZh: '稳定',   color: 'var(--success)' },
  beta:       { label: 'Beta',       labelZh: '测试版', color: '#0A59F7' },
  deprecated: { label: 'Deprecated', labelZh: '已废弃', color: 'var(--text-3)' },
};

const COMP_CAT_LABELS = {};
COMPONENTS.forEach(c => { if (!COMP_CAT_LABELS[c.category]) COMP_CAT_LABELS[c.category] = c.categoryZh; });
const COMP_CATEGORIES = Object.keys(COMP_CAT_LABELS);

/* Which tokens each component consumes — lets the relationship graph show EVERY
   component, not only the ones with component-layer tokens. Wired components list
   their own component tokens; the rest map to the semantic tokens they use. */
const COMP_CONSUME_BY_CAT = {
  'Foundation':   ['color.accent.default','color.text.primary','color.border.default','color.bg.surface','radius.control'],
  'Navigation':   ['color.accent.default','color.text.primary','color.text.secondary','color.bg.surface','color.border.default'],
  'Data entry':   ['color.bg.surface','color.border.default','color.text.primary','color.accent.default','radius.control'],
  'Data display': ['color.bg.surface','color.border.default','color.text.primary','color.text.secondary','radius.surface'],
  'Feedback':     ['color.status.danger','color.status.success','color.status.warning','color.text.onAccent','color.bg.surface'],
};
const COMPONENT_CONSUMES = {};
COMPONENTS.forEach(c => {
  const own = TOKENS.filter(t => t.layer === 'component' && t.id.split('.')[0] === c.id).map(t => t.id);
  COMPONENT_CONSUMES[c.id] = own.length ? own : (COMP_CONSUME_BY_CAT[c.category] || ['color.text.primary','color.bg.surface']);
});

Object.assign(window, { COMPONENTS, COMPONENT_MAP, tokensUsedBy, COMP_STATUS, COMP_CATEGORIES, COMP_CAT_LABELS, COMPONENT_CONSUMES });
