Files
inkreach-agent/docs/plugins/07-ui-components.md

4.0 KiB
Raw Permalink Blame History

L6 · 公共 UI 组件库(@aso/plugin-sdk/ui)

前置:L4 React 组件。约 15 分钟。 目标:不写一行样式代码,做出与宿主完全一致的界面;等待/失败/空态不再自造。

为什么必须用它

DESIGN.md 定了「长什么样」,组件库把它变成「直接拿来的代码」:

  • token 同源:组件内部只用宿主已核验的类词汇(text-ink-3、rounded-control…) 与 var(--token) 内联变量,深浅色自动跟随宿主主题
  • 三态统一:等待 LoadingState / 失败 ErrorState(可重试)/ 空 EmptyState, 任何插件的加载体验与宿主一致
  • 零依赖:./ui 是 sdk 源码子路径,随 esbuild 一起打进 renderer.mjs, 不引任何第三方 UI 库(shadcn/ui 的思路——无运行时、复制即用——由宿主承担)

导入与构建

import { Button, LoadingState, ErrorState, EmptyState, SettingRow, Switch } from '@aso/plugin-sdk/ui'

构建命令与 L4 完全相同——ui 随 sdk 源码一起被打包,react 别名照旧:

esbuild src/renderer.tsx --bundle --format=esm --outfile=renderer.mjs \
  --jsx=automatic --alias:react=./shims/react.js --alias:react/jsx-runtime=./shims/jsx-runtime.js

组件目录

组件 用途 要点
Spinner 行内旋转指示 size 默认 14px
LoadingState 区块等待态 label 可换文案,默认「加载中…」
ErrorState 区块失败态 title/description(错误消息)、onRetry 提供即显示重试按钮
EmptyState 区块空态 title + description + action(如「去设置」按钮)
Button 按钮 variant: 'primary' | 'ghost' | 'danger';loading 置灰并显示 Spinner,防重复提交
Input / Textarea 输入 与宿主设置页同款外观
Select 下拉 options: { value, label }[],原生 select
Switch 开关 受控 checked/onCheckedChange,或非受控 defaultChecked
Card 卡片容器 rounded-card + line 边框
SettingRow 设置行 label 左 / 控件右(DESIGN §4 标准模式)
Badge 徽标 tone: 'neutral' | 'accent' | 'danger',版本/来源/状态元信息

全部组件接受 className 追加布局类(flex/间距/尺寸),不接受颜色/字号覆写—— 那两条路(hex、新字号)被 L7 检验器拦截。

三态铁律

任何异步区块的状态机:loading → data | error | empty,四选一,不允许第五种 (白屏、裸文本「加载中」、无反馈的失败)。模板(plugin-template)是完整示范:

{error !== null ? (
  <ErrorState title="数据加载失败" description={error} onRetry={() => setTick((t) => t + 1)} />
) : items === null ? (
  <LoadingState label="正在拉取数据…" />
) : items.length === 0 ? (
  <EmptyState title="暂无数据" description="检查数据源后点击重新加载" />
) : (
  items.map((it) => <SettingRow key={it} label={it} />)
)}

配套铁律:异步调用必须 withTimeout/withRetry(见 L7),否则 loading 态可能永远挂着。

宿主兜底

renderer 模块的读源与 import 宿主各限时 8 秒:超时或失败时,插件槽位自动呈现宿主侧 「插件界面装载失败」ErrorState(带重试按钮);组件渲染期崩溃由 PluginErrorBoundary 兜底。也就是说装载失败不需要插件自己处理,插件只需管好自己组件内部的异步。

边界

  • 仅 renderer 组件槽位可用(渲染在宿主 DOM,复用宿主样式表);iframe 插件页是物理 隔离文档,请按 DESIGN.md §4 的 HTML 模式自行实现
  • 需要新形态时:先用现有组件拼;确实不够,在 DESIGN.md 约束内组合 token, 并把新形态沉淀回团队公共代码,而不是留在单个插件里

上一篇 L5 自诊断 · 下一篇:L7 性能与检验——超时、重试与机器关卡。