ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Cloudflare Agents 前端视觉体系实战:基于 Kumo 设计系统构建 Agent Playground 界面

Cloudflare Agents 前端视觉体系实战:基于 Kumo 设计系统构建 Agent Playground 界面 Cloudflare Agents 前端视觉体系实战基于 Kumo 设计系统构建 Agent Playground 界面【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents本文以仓库中的 design/visuals.md 为核心系统讲解 Cloudflare Agents 项目GitHub_Trending/agents1/agents如何基于 Cloudflare 内部设计系统Kumocloudflare/kumo统一构建所有示例与 Playground 的前端界面。你将掌握 Kumo 与 Tailwind v4 的集成方式、基于data-mode的自动明暗模式切换、LinkProvider与 React Router 的类型适配方案以及设计系统能力不足时如何用自定义组件补齐缺口的工程决策。一、设计系统选型为什么使用 KumoPlayground以及后续所有示例统一采用 Cloudflare 内部设计系统 Kumocloudflare/kumo而不是自建组件原语。它带来了三层核心收益语义化颜色令牌semantic color tokens如bg-kumo-base、text-kumo-default、border-kumo-line颜色含义由语义驱动而非固定色值无障碍组件按钮、输入框、表单控件等均内置 ARIA 支持自动明暗模式无需在每个组件上手动维护主题逻辑。从仓库看这一决策已贯穿整个示例体系examples/下几乎所有示例的src/client.tsx与src/styles.css都导入了 Kumo而 Playground 是落地最完整的参考实现入口见 examples/playground/src/client.tsx。依赖清单在 examples/playground/package.json 中可以确认以下关键依赖依赖版本作用cloudflare/kumo^2.6.0设计系统组件库monorepo 根目录安装为 devDependencyphosphor-icons/react^2.1.10Kumo 的配套图标库peer 依赖tailwindcss/vite^4Tailwind v4 的 Vite 插件图标使用规范永远使用*Icon后缀导出phosphor-icons/reactv2 中带Icon后缀的导出如TrashIcon、ShieldIcon是推荐用法裸名Trash、Shield已废弃。仓库中的真实调用印证了这一点examples/playground/src/components/LogPanel.tsx 中使用了TrashIconexamples/playground/src/layout/Sidebar.tsx 中大量使用CaretDownIcon、CaretRightIcon、CubeIcon、ChatDotsIcon、MoonIcon、SunIcon等。二、环境搭建Tailwind v4 与 Kumo 的集成Kumo 自带 Tailwind 插件需要在 Vite 构建链路中挂载tailwindcss/vite并在 CSS 入口中显式导入。Vite 配置examples/playground/vite.config.ts 中的插件顺序为import { cloudflare } from cloudflare/vite-plugin; import tailwindcss from tailwindcss/vite; import react from vitejs/plugin-react; import agents from agents/vite; import { defineConfig } from vite; export default defineConfig({ plugins: [agents(), react(), tailwindcss(), cloudflare()], define: { __filename: index.ts } });tailwindcss()插件与vitejs/plugin-react、cloudflare/vite-plugin并列注册。注意这里的agents()是 agents SDK 自己的 Vite 插件负责在本地开发时注入 Worker 运行时。styles.css 的三行关键配置examples/playground/src/styles.css 顶部import tailwindcss; import cloudflare/kumo/styles/tailwind; /* Tailwind ignores node_modules by default, so we source Kumo for class extraction. */ source ../node_modules/cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx};这里有一个重要的工程细节Tailwind 默认忽略node_modules因此必须用source指令将 Kumo 的产物目录纳入类名提取范围否则 Kumo 组件内部使用的语义类bg-kumo-base等不会被生成。关于source路径文档特别强调了一个易踩的坑source路径是相对于src/styles.css的即../node_modules它指向示例自己的node_modules。这个写法在 pnpm workspace 中每个包都有自己的带符号链接的node_modules与示例被单独复制出去独立安装两种场景下都能正确解析因此不要写成../../../node_modules这类 monorepo 根目录相对路径。其他示例的对比以 examples/channels/src/styles.css 等为代表的示例同样遵循这一模式验证了这是整个示例体系的统一约定而非 Playground 独有。三、明暗模式data-mode属性驱动的主题系统与常见的 Tailwinddark:类前缀方案不同Kumo 使用html元素上的data-mode属性控制主题。所有 Kumo 语义令牌bg-kumo-base、text-kumo-default、border-kumo-line等会自动响应这个属性整个代码库中不需要任何dark:前缀。这套机制由两个部分配合完成1. index.html 中的首屏防闪烁脚本examples/playground/index.html 的head内联脚本在页面加载前同步执行script (() { const mode localStorage.getItem(theme) || light; document.documentElement.setAttribute(data-mode, mode); document.documentElement.style.colorScheme mode; })(); /script它在 React 应用挂载之前就把data-mode写入html避免了明暗主题切换时的白屏/闪烁FOUC。同时设置了style.colorScheme让浏览器原生控件滚动条、表单控件也跟随主题。2. 内联 ModeToggle 组件每个示例内置一份ModeToggle组件不共享自公共包负责运行时切换。examples/playground/src/layout/Sidebar.tsx 中的实现如下function ModeToggle() { const [mode, setMode] useState( () localStorage.getItem(theme) || light ); useEffect(() { document.documentElement.setAttribute(data-mode, mode); document.documentElement.style.colorScheme mode; localStorage.setItem(theme, mode); }, [mode]); return ( Button variantghost shapesquare aria-labelToggle theme onClick{() setMode((m) (m light ? dark : light))} icon{mode light ? MoonIcon size{16} / : SunIcon size{16} /} / ); }工作流程是useState读取localStorage中的theme作为初始值 →useEffect将模式写入data-mode与colorScheme并持久化 → 点击按钮在light/dark间切换图标也随之从MoonIcon变为SunIcon。色彩主题Color Themes所有示例目前均使用 Kumo 的默认主题没有任何自定义主题覆盖。Kumo 支持通过父元素上的data-theme属性进行主题定制但现有示例全部省略该属性。这意味着如果你的 Agent 应用需要品牌色主题可以在未来通过data-theme扩展而无需改动组件代码。四、标准 UI 模式清单每个示例都包含以下 UI 元素且是内联在每个示例中而非从公共包导出模式来源用途PoweredByCloudflarecloudflare/kumoPowered by Cloudflare 页脚徽标——每个示例都应包含CloudflareLogocloudflare/kumoCloudflare Logo 组件含 glyph / full 两种变体ModeToggle每个示例内联基于localStoragedata-mode属性的明暗切换ConnectionIndicator每个示例内联彩色圆点 标签展示 WebSocket 状态connecting/connected/disconnectedConnectionIndicator 的实际实现examples/playground/src/components/ConnectionStatus.tsx 给出了完整的连接状态指示器实现。它用一个statusConfig配置表把三种状态映射到语义类与颜色const statusConfig { connected: { label: Connected, dot: bg-green-500, text: text-kumo-success, bg: bg-green-500/10 }, connecting: { label: Connecting…, dot: bg-kumo-warning animate-pulse, text: text-kumo-warning, bg: bg-kumo-warning-tint }, disconnected: { label: Disconnected, dot: bg-kumo-danger, text: text-kumo-danger, bg: bg-kumo-danger-tint } } as const;组件渲染为一个带彩色圆点的圆角徽章连接成功后还会追加显示agentName/instanceName让用户直观看到自己连接到了哪个 Agent 实例。五、路由集成KumoLinkProvider与 React Router 的类型适配Kumo 的LinkProvider允许注入自定义链接组件让Link通过你的路由库渲染。但在接入 React Router 时存在一个类型不匹配问题Kumo 的LinkComponentProps定义to?: string可选React Router 的Link要求to: To必选且To string | PartialPath。这两个类型在任一方向上都不互相可赋值直接把RouterLink传给LinkProvider会报类型错误。解决方案AppLink 适配器仓库在 examples/playground/src/client.tsx 中用一个极薄的适配组件桥接两者import { LinkProvider, type LinkComponentProps } from cloudflare/kumo; const AppLink forwardRefHTMLAnchorElement, LinkComponentProps( ({ to, ...props }, ref) { if (to) { return RouterLink ref{ref} to{to} {...props} /; } // oxlint-disable-next-line jsx-a11y/anchor-has-content -- content comes from spread props return a ref{ref} {...props} /; } ); function App() { return ( LinkProvider component{AppLink} BrowserRouter Routes.../Routes /BrowserRouter /LinkProvider ); }这个适配器做了两件事兜底可选性缺口to存在时渲染为RouterLinkto缺失时退化为普通a与 Kumo 实际只会传入字符串to的行为对齐收窄类型将To收窄为string这正是 Kumo 在实际调用中始终传入的类型。此外仓库还保留了oxlint-disable注释来说明裸a无内容时的无障碍检查豁免——内容通过展开的 props 提供。上游修复建议文档指出这个问题值得向 Kumo 团队提出因为每个使用 React Router 的开发者都会遇到。可能的修复方向有三个Kumo 将LinkComponentProps的to改为必填组件实际被调用时总是提供该值Kumo 直接接受 React Router 的To类型React Router 放宽Link接受to?: string。六、Kumo 组件选用清单以下是 Playground 中实际使用的 Kumo 组件与其替换的自研组件Kumo 组件替换对象 / 用途Button所有按钮primary / secondary / destructive / ghost 操作Input文本输入框用内置labelprop 作为 Field 包装InputArea多行文本框Surface卡片 / 面板容器Text标题与正文注意不接受className需要 margin/spacing 时外层包divBadge状态指示与标签Banner告警 / 警告横幅CodeBlock静态代码示例与动态 JSON 展示Tabs标签页切换如 inbox/outboxSwitch布尔开关内置 labelCheckbox多选复选框Table数据表格Empty空状态占位Loader加载 spinnerLinkProvider/Link路由感知链接以 examples/playground/src/demos/core/RoutingDemo.tsx 为例可以同时看到多个组件的组合用法Surface承载控制面板Text variantheading3渲染小节标题外层用div classNamemb-4控制间距正是文档提到的Text不接受className的应对方式Input labelUser ID ...提供带标签输入框Radio.Group/Radio.Item实现策略选择。七、自定义实现及其原因Kumo 能力边界Kumo 并非覆盖一切场景Playground 在以下几处保留了自研实现每个决策都有明确理由1. 侧边栏分类折叠Sidebar category toggleexamples/playground/src/layout/Sidebar.tsx 中的CategorySection使用原生button实现分类的展开/收起。原因是 Kumo 的Collapsible只接受label: string而导航分类需要图标 文本的组合内容。该按钮还通过aria-expanded、aria-controls维护无障碍语义配合CaretDownIcon/CaretRightIcon指示折叠状态。2. 路由策略选择器RoutingDemoRoutingDemo需要一个每项既有标题又有描述的类单选 UI而 Kumo 的Radio.Item只支持label: string无法容纳 per-option 的描述。从 examples/playground/src/demos/core/RoutingDemo.tsx 可以看到它的折中方案在Radio.Item的 label 中用—拼接标题与描述如Per-User — Each user ID gets their own agent instance并在侧栏用标题 副文案结构展示四种策略的完整说明。3. 交互式列表项房间列表ChatRoomsDemo、表格列表SqlDemo、邮件列表ReceiveDemo、SecureDemo以及审批预设按钮ApprovalDemo都使用被样式化为列表行的原生button。这些是带复杂 active/hover 状态的选择驱动型列表行不属于标准按钮模式而 Kumo 没有可复用的可选列表组件。4. 范围滑块BasicDemoWorkflow 步骤数滑块使用原生input typerange因为 Kumo 未提供 range/slider 组件。5. 日志面板LogPanel事件日志使用styles.css中定义的少量自定义 CSS 工具类.log-entry、.log-entry-in、.log-entry-out、.log-entry-error它们是整个代码库中仅有的自定义 CSS 类。原因在于日志条目是高密度、领域特定的模式Kumo 没有对应组件。examples/playground/src/styles.css 中的实际定义展示了如何用layer components与apply组合语义令牌layer components { .log-entry { apply px-3 py-1.5 text-xs font-mono text-kumo-default border-b border-kumo-fill last:border-0; } .log-entry-in { apply bg-green-500/10; } .log-entry-out { apply bg-kumo-info-tint; } .log-entry-error { apply bg-kumo-danger-tint text-kumo-danger; } .log-entry-info { apply bg-kumo-base; } }对应消费方 examples/playground/src/components/LogPanel.tsx 根据日志方向in/out/error/info选择不同的类组合并以←、→、✕、•分别标记方向同时自动滚动到底部。6. 语义色令牌缺口当前已知限制有几个期望存在的 Kumo 语义令牌目前尚不存在仓库中的回退方案是bg-kumo-success-tint/bg-kumo-success→ 回退为bg-green-500/10/bg-green-500border-l-kumo-success→ 回退为border-l-green-500文档明确警示这些原生 Tailwind 绿色不会随data-theme变化它们绕过了令牌系统应在 Kumo 上游补齐对应令牌后替换。这个回退但不完美的处理思路也值得借鉴先用可用的类保证功能与视觉同时在代码中留下待替换标记。八、整体架构与布局实践从 examples/playground/src/layout/Layout.tsx 可以看到完整的页面骨架移动端顶栏md:hidden包含打开侧栏的 ghost 按钮、PoweredByCloudflare徽标桌面端为静态侧栏移动端为覆盖式抽屉带遮罩层主内容区flex-1 overflow-y-auto bg-kumo-base承载路由出口Outlet。侧栏导航数据定义在 examples/playground/src/layout/Sidebar.tsx 顶部的navigation数组按 Core / AI / Durable Execution / MCP / Workflows / Multi-Agent / Voice / Email / Product Integrations 分类组织每个分类带图标条目用 React Router 的NavLink渲染根据isActive切换高亮样式。移动端侧栏在路由变化时自动关闭useEffect监听location.pathname。九、实践要点总结统一设计系统Kumo 提供语义令牌、无障碍组件与自动明暗模式examples/全部示例统一使用可参考 examples/playground/src/styles.css 作为基线工具链组合tailwindcss/vitecloudflare/kumo/styles/tailwindsource提取声明三者缺一不可主题不写dark:通过data-modelocalStorage 首屏内联脚本实现无闪烁的主题切换路由类型桥接AppLink适配器是 Kumo × React Router 组合的标准解法完整代码在 examples/playground/src/client.tsx承认边界当设计系统缺少所需组件滑块、可折叠带图标、可选列表等时保留原生元素 语义类的自研方案并注意避免非语义色值破坏主题一致性。【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表