关于 gpui-kit
gpui-kit 是面向使用 Rust gpui-kit crate 构建应用的编码 Agent 的 Skill。它要求先查阅设计与编码指南,并列出表单、反馈、弹层、导航和数据展示等组件。
主要功能
- 01crate 分层与状态归属指导
- 02设计和编码指南参考
- 03UI 组件目录
- 04有状态与无状态组件模式
- 05主题、弹层与布局指导
适用场景
- 01为 UI 任务选择组件
- 02实现表单和交互控件
- 03使用弹层与导航构建应用视图
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ longbridge/ gpui-kit --skill gpui-kit安装后在 Claude Code 中输入/gpui-kit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/coding-guides.mdconventions.mdrecipes.mdusage.mdreferences/gpui/action.mdasync.mdcontext.mdelement-advanced.mdelement-api.mdelement-best-practices.mdelement-examples.mdelement-id.mdelement-patterns.mdelement.mdentity-advanced.mdentity-api.mdentity-best-practices.mdentity-patterns.mdentity.mdevent.mdfocus-handle.mdglobal.mdlayout-style.mdtest-examples.mdtest-reference.mdtest.md详细介绍
GPUI Kit
应用依赖一个 crate:gpui-kit。GPUI 的导入方式为 use gpui_kit::*;,每一层都可通过名称访问:gpui_kit::component(带样式的组件)、gpui_kit::base(无样式的行为)、gpui_kit::assets(默认图标)、gpui_kit::platform。
请先阅读组件系列约定,根据任务选择构造函数、状态所有者、事件和布局约定。先了解组件系列,再确认具体组件是否支持所需功能。
如需了解包含保留状态、订阅和覆盖层的完整编译视图,请阅读经过测试的应用配方。
先阅读指南
本技能依赖两份指南中的规则。这些规则是要求,不是参考建议。请直接阅读指南文件;不要依据本页面、代码库中的相似文件或训练数据作答。
| 指南 | 阅读时机 |
|---|---|
设计指南,技能 gpui-kit-design-guides | 选择组件、布局、间距、层级、颜色、密度、交互状态、覆盖层、动效和界面文案时 |
| 编码指南 | crate 分层、RenderOnce 与 Entity<T> 的取舍、状态所有权、ElementId、事件、焦点、异步操作、公共 API、命名和测试相关任务开始前 |
当更改会影响可见界面时,请先阅读设计指南:代码结构应保留产品意图,而不能取而代之。如果尚未安装设计技能,请获取 https://gpui-kit.com/docs/design-guides.md。编码指南是 https://gpui-kit.com/docs/coding-guides.md 的逐字副本,因此其中指向 ./design-guides.md 和 ./getting-started.md 的链接分别指向设计技能和 https://gpui-kit.com/docs/getting-started.md。
Coding Guides 章节索引
为新的 crate、模块或功能通读整篇指南。对于范围较窄的更改,先阅读“架构概览”和“编码 Agent 规则”,然后阅读与更改相关的章节(grep -n '^## ' references/coding-guides.md)。
| 章节 | 阅读时机 |
|---|---|
| 架构概览 | 始终阅读;crate 分层、所有权边界 |
| 引导与根所有权 | 涉及 main、init、Root、窗口创建、应用级状态时 |
| 理解 GPUI 的阶段与上下文 | 涉及 App、Window、Context<T>、render 与 update 的区别时 |
| 选择合适的单元 | 决定使用 RenderOnce、Entity<T> 还是自定义 Element 时 |
| 状态所有权 | 确定状态的存放位置、修改者、Entity<State> 句柄时 |
| 稳定标识 | 涉及 ElementId、列表、重复元素、带键状态时 |
| 渲染与组合 | 涉及 render、构建器链、when/map、子项组合时 |
| 行为与呈现边界 | 涉及 gpui-base、gpui-component 与应用代码之间的划分时 |
| 主题与样式 | 涉及 cx.theme()、tokens、Styled、尺寸、变体时 |
| 事件、操作与焦点 | 涉及 cx.emit、subscribe、actions!、键绑定、FocusHandle 时 |
| 异步工作与副作用 | 涉及 cx.spawn、background_spawn、Task、I/O、计时器时 |
| 布局、测量与滚动 | 涉及 Flex 布局、尺寸、overflow、滚动句柄、测量时 |
| 列表、表格与大型数据 | 涉及 VirtualList、List、DataTable、委托对象、大型集合时 |
| 公共 API 设计 | 涉及任何 pub 项:构建器、私有字段、setter 和读取方法的命名 |
| 平台与能力边界 | 涉及 macOS/Windows/Linux/wasm 差异、功能门控时 |
| 文件与命名约定 | 涉及新文件、模块、类型和方法名、Kind 后缀、Context 时 |
| 测试策略 | 确定测试内容、使用 #[gpui_kit::test]、TestAppContext 时 |
| 性能规则 | 涉及渲染开销、分配、重新渲染触发条件时 |
| 常见失败模式 | 完成前阅读;虚构 API、在 render 中存放状态、使用索引 ID |
| 编码 Agent 规则 | Agent 编写代码时始终阅读 |
| 实现检查清单 | 完成前阅读;逐项检查工作是否满足要求 |
不容妥协的原则
这是最低要求,不能替代指南。
- 绝不虚构 API。 在当前源码中查找实际签名。 不要类比翻译 React、CSS 或旧版 GPUI 示例;看似合理但实际不存在的方法是最常见的失败原因。
- 仅依赖一个依赖项。 应用只依赖
gpui-kit。GPUI 的引入方式是use gpui_kit::*;;各层分别为gpui_kit::component、gpui_kit::base、gpui_kit::assets、gpui_kit::platform。 - 框架负责行为,应用负责呈现。 不要在
gpui-base中放置颜色、尺寸或布局;不要在应用样式代码中放置交互行为。 - 稳定标识。 重复元素需要由领域数据生成的
ElementId,而非列表索引。 - 跨边界时不使用
pub字段。 公共数据类型使用构建器和读取方法。 - 明确写出
Context。cx属于 GPUI;其他内容应按其所持有的内容命名。
文档
- 查找任务/组件页面:使用
https://gpui-kit.com/llms.txt,然后加载其 Markdown 页面。 - 完整参考:仅在确实需要广泛参考时使用
https://gpui-kit.com/llms-full.txt - 单个组件 API:获取
https://gpui-kit.com/component/{name}.md, 例如button.md、input.md、select.md、dialog.md、data-table.md - 任何站点页面都可以通过在 URL 后追加
.md获取 Markdown 格式
快速参考
设置和示例:references/usage.md。
use gpui_kit::*;
gpui_kit::application()
.with_assets(gpui_kit::assets::Assets)
.run(|cx| {
gpui_kit::init(cx); // first, before anything else
gpui_kit::open_window(options, cx, |window, cx| {
cx.new(|cx| AppView::new(window, cx))
})
.expect("failed to open window");
});
- 无状态(
RenderOnce):在render中构建:Button::new("save").primary().label("Save").on_click(|_, _, _| {}) - 有状态:在视图中持有
Entity<State>,在render中传入引用:let input = cx.new(|cx| InputState::new(window, cx));然后使用Input::new(&self.input) - 尺寸:
.xsmall().small().medium()(默认).large() - 主题:
cx.theme().primary·.background·.foreground·.border·.muted - 叠加层:通过
gpui_kit::component::WindowExt使用window.open_dialog(...)、open_sheet(...)、push_notification(...)
组件目录
导入路径相对于 gpui_kit::component::,因此 input::{Input, InputState}
表示 use gpui_kit::component::input::{Input, InputState};。如需完整 API,
请获取该组件的 .md 文档。
输入与表单
| 组件 | 导入 | 说明 |
|---|---|---|
Input | input::{Input, InputState} | 有状态。文本、密码、遮罩、验证 |
Textarea | input::{Textarea, TextareaState} | 有状态。多行文本 |
Editor | input::{Editor, EditorState} | 有状态。代码编辑器,tree-sitter feature |
NumberInput | input::{NumberInput, NumberInputEvent} | 有状态。带步长的数值输入 |
OtpInput | input::OtpInput | 有状态。一次性密码 |
SpeechButton | speech::{SpeechButton, SpeechState} | 有状态。听写,speech feature |
Select | select::{Select, SelectState} | 有状态。下拉选择器 |
Combobox | combobox::{Combobox, ComboboxState} | 有状态。可搜索的选择器 |
Checkbox | checkbox::Checkbox | 无状态。on_click 接收 &bool |
Switch | switch::Switch | 无状态。切换开关 |
Radio | radio::{Radio, RadioGroup} | 无状态。 |
Slider | slider::{Slider, SliderState} | 有状态。 |
Toggle | button::Toggle | 无状态。 |
Rating | rating::Rating | 无状态。 |
Stepper | stepper::Stepper | 无状态。多步进度 |
ColorPicker | color_picker::{ColorPicker, ColorPickerState} | 有状态。 |
DatePicker | date_picker::{DatePicker, DatePickerState} | 有状态。 |
TimeField | time_field::{TimeField, TimeFieldState} | 有状态。一天中的时间,24/12 小时制 |
Calendar | calendar::{Calendar, CalendarState} | 有状态。内嵌月历视图 |
Form | form::{v_form, h_form, field} | 表单字段的布局容器 |
显示与反馈
| 组件 | 导入 | 说明 |
|---|---|---|
Button | button::{Button, ButtonGroup} | 无状态。主要 UI 操作 |
Icon | {Icon, IconName} | 无状态。Lucide 图标 |
Badge | badge::Badge | 无状态。 |
Tag | tag::Tag | 无状态。可关闭标签 |
Avatar | avatar::Avatar | 无状态。 |
Label | label::Label | 无状态。表单标签 |
Kbd | kbd::Kbd | 无状态。键盘按键显示 |
Alert | alert::Alert | 无状态。信息/成功/警告/错误 |
Spinner | spinner::Spinner | 无状态。加载指示器 |
Skeleton | skeleton::Skeleton | 无状态。加载占位符 |
Shimmer | shimmer::{ShimmerText, ShimmerStyle} | 无状态。流式文本光效 |
Marker | marker::{Marker, MarkerVariant} | 无状态。行内状态标记 |
Progress | progress::{Progress, ProgressCircle} | 无状态。 |
Tooltip | tooltip::Tooltip | 在元素上通过 .tooltip() 使用 |
HoverCard | hover_card::{HoverCard, HoverCardState} | 有状态。 |
Clipboard | clipboard::Clipboard | 无状态。复制按钮 |
TextView | text::TextView | TextView::markdown(id, text),也支持 HTML |
| Image | gpui_kit::{img, ImageSource, ObjectFit} | GPUI 的 img() 元素 |
覆盖层与弹出窗口
| 组件 | 导入 | 说明 |
|---|---|---|
Dialog | dialog::Dialog + WindowExt | 通过 window.open_dialog(...) 使用 |
AlertDialog | WindowExt | 通过 window.open_alert_dialog(...) 使用 |
Sheet | sheet::Sheet + WindowExt | 侧边面板,通过 window.open_sheet(...) 使用 |
Notification | notification::Notification + WindowExt | 通过 window.push_notification(...) 使用 |
Popover | popover::Popover | 浮动覆盖层 |
Menu | menu::{PopupMenu, DropdownMenu} | 上下文菜单 |
DropdownButton | button::DropdownButton | 带下拉菜单的按钮 |
Command | command::{Command, CommandState, CommandGroup} | 有状态。命令面板 |
| 焦点陷阱 | FocusTrapElement | 在容器上使用 .focus_trap(id, &handle);Dialog 和 Sheet 内置此功能 |
导航与布局
| 组件 | 导入 | 说明 |
|---|---|---|
Tabs / TabBar | tab::{Tab, TabBar} | 标签页界面 |
Sidebar | sidebar::{Sidebar, SidebarMenu, ...} | 应用导航面板 |
TitleBar | TitleBar | 窗口标题栏 |
StatusBar | status_bar::StatusBar | 窗口状态栏 |
Breadcrumb | breadcrumb::Breadcrumb | 导航面包屑 |
Pagination | pagination::Pagination | 页面导航 |
Accordion | accordion::Accordion | 可折叠分区 |
Collapsible | collapsible::Collapsible | 单个可折叠项 |
GroupBox | group_box::GroupBox | 带标签的容器 |
Resizable | resizable::{h_resizable, v_resizable, resizable_panel, ResizableState} | 可拖动的分栏 |
ResizeHandle | resizable::{resize_handle, HandleEdge} | 独立的调整大小边缘 |
Scrollbar | scroll::Scrollbar | 自定义滚动条 |
数据展示
| 组件 | 导入 | 说明 |
|---|---|---|
DataTable | table::{DataTable, TableState, TableDelegate} | 有状态。功能完备的表格 |
Diff | diff::{Diff, DiffState, DiffFile} | 保留状态的 RenderOnce 元素。只读的统一/Git 差异显示,可展示一个或多个文件、合并冲突和源文件;补丁由应用提供 |
Table | table::{Table, ...} | 更简单的表格 |
VirtualList | {v_virtual_list, h_virtual_list} | 高性能大型列表 |
List | list::{List, ListState, ListDelegate} | 有状态。可搜索的列表 |
Tree | tree::{Tree, TreeState, TreeItem, TreeEntry} | 有状态。层级结构 |
DescriptionList | description_list::DescriptionList | 键值对 |
Settings | setting::Settings | 设置面板 |
聊天与消息
| 组件 | 导入 | 说明 |
|---|---|---|
Message | message::{Message, MessageContent, MessageAlignment} | 无状态。聊天消息行 |
Bubble | bubble::{Bubble, BubbleContent, BubbleVariant} | 无状态。消息气泡 |
Attachment | attachment::{Attachment, AttachmentContent, ...} | 无状态。文件/媒体附件卡片 |
MessageScroller | message_scroller::{MessageScroller, MessageScrollerState} | 有状态。自动滚动的消息列表 |
图表
| 组件 | 导入 | 说明 |
|---|---|---|
Chart | chart::{AreaChart, BarChart, LineChart, PieChart, RadarChart} | 柱状图、折线图、面积图、饼图 |
Plot | plot::Plot | 使用 #[derive(IntoPlot)] 处理数据 |
测试
UI 集成测试是指在无头窗口中渲染真实组件、模拟输入,并检查状态、焦点、布局和所有者回调。使用
#[gpui_kit::test] 运行测试,并使用 gpui_kit::test 操作和检查 UI。
当被要求添加组件交互覆盖时,请将其描述为 UI 集成测试。
如需了解单元测试、GPUI 上下文测试或 UI 集成测试,请阅读 测试。其中包含依赖项配置、完整可运行的 UI 流程、限定范围的原生交互、帧和异步处理,以及无障碍和几何断言的局限性。使用生产视图,并通过常规 Rust 断言验证操作结果。
GPUI 参考资料
加载与任务涉及的机制对应的文件。每个文件都以目录行开头。
| 主题 | 文件 | 适用场景 |
|---|---|---|
| 操作与快捷键绑定 | action.md | actions!、bind_keys、on_action、key_context |
| 异步与后台任务 | async.md | cx.spawn、background_spawn、Task、异步 I/O |
| 上下文管理 | context.md | App、Window、Context<T>、AsyncApp |
| 自定义元素(底层) | element.md | Element trait、request_layout、prepaint、paint |
| 实体状态 | entity.md | Entity<T>、WeakEntity、状态管理 |
| 事件与订阅 | event.md | cx.emit、cx.subscribe、cx.observe |
| 焦点与键盘导航 | focus-handle.md | FocusHandle、track_focus、Tab 导航 |
| 全局状态 | global.md | Global trait、cx.set_global、应用级配置 |
| 布局与样式 | layout-style.md | div()、h_flex()、v_flex()、flexbox、溢出、定位 |
| ElementId | element-id.md | ElementId、.id()、唯一性规则、有状态元素 |
| 测试 | test.md | #[gpui_kit::test]、TestAppContext、VisualTestContext |
深入资料:当主题文件无法满足需求时,可查阅:
- Element trait:element-api.md(完整 API、命中框、事件)· element-patterns.md(文本、交互式、容器、复合元素)· element-examples.md(完整示例)· element-best-practices.md(性能、状态、常见问题)· element-advanced.md(自定义布局、异步更新、虚拟列表)
- 实体:entity-api.md(完整 API、生命周期)· entity-patterns.md(模型-视图、跨实体、观察者)· entity-best-practices.md(内存、性能)· entity-advanced.md(集合、注册表、防抖、状态机)
- 测试:test-examples.md(组织、设置、断言、运行测试)· test-reference.md(可重入性、属性测试、模拟)