gpui-components
3
总安装量
2
周安装量
#55633
全站排名
安装命令
npx skills add https://github.com/terraphim/opencode-skills --skill gpui-components
Agent 安装分布
opencode
2
mcpjam
1
claude-code
1
junie
1
windsurf
1
zencoder
1
Skill 文档
GPUI Components Skill
Generates production-ready Rust code for GPUI desktop UI components following patterns from Zed editor and gpui-component library.
When to Use This Skill
- Building desktop UI applications with GPUI framework
- Creating custom components using
RenderOnceorRendertraits - Implementing themed components with
ActiveTheme - Building autocomplete/completion menus
- Creating command palettes and popup menus
- Working with
gpui-componentcrate
Core GPUI Concepts
Application Setup
use gpui::{Application, Window, Context, div, px, rgb};
use gpui_component::{init, Root, Theme};
fn main() {
Application::new().run(|cx| {
// Initialize gpui-component
gpui_component::init(cx);
cx.open_window(
WindowOptions::default(),
|window, cx| Root::new(MyApp::new(cx), window, cx)
);
});
}
Component Patterns
RenderOnce (Stateless)
use gpui::{IntoElement, RenderOnce, Styled, div};
#[derive(IntoElement)]
pub struct MyButton {
label: SharedString,
variant: ButtonVariant,
}
impl RenderOnce for MyButton {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.px_3()
.py_2()
.bg(cx.theme().primary)
.text_color(cx.theme().primary_foreground)
.rounded_md()
.child(self.label)
}
}
Render with Entity (Stateful)
use gpui::{Entity, Render, Context};
pub struct Counter {
count: i32,
}
impl Render for Counter {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.gap_2()
.child(Button::new("dec").on_click(cx.listener(|this, _, _, cx| {
this.count -= 1;
cx.notify();
})))
.child(format!("Count: {}", self.count))
.child(Button::new("inc").on_click(cx.listener(|this, _, _, cx| {
this.count += 1;
cx.notify();
})))
}
}
Available Components (gpui-component)
Form Components
Button– Buttons with variants (primary, danger, ghost, link)Input– Text input with LSP completion supportNumberInput– Numeric input with step controlsCheckbox– Checkbox with labelSwitch– Toggle switchRadio– Radio button groupsSelect– Dropdown selectSlider– Range slider
Layout Components
Dialog– Modal dialogsPopover– Popup popoversMenu/PopupMenu– Menus and context menusTab– Tab navigationAccordion– Collapsible sectionsSidebar– Sidebar navigationDock– Dockable panels
Display Components
Badge– Status badgesAvatar– User avatarsIcon– Icon display (IconName enum)Label– Text labelsTooltip– TooltipsNotification– Toast notifications
Data Components
Table– Data tablesList/VirtualList– Scrollable listsTree– Tree viewChart– Charts and plots
Theming
Accessing Theme
use gpui_component::ActiveTheme;
fn render(&mut self, window: &mut Window, cx: &mut App) -> impl IntoElement {
div()
.bg(cx.theme().background)
.text_color(cx.theme().foreground)
.border_1()
.border_color(cx.theme().border)
}
Theme Colors
// Background colors
cx.theme().background // Primary background
cx.theme().secondary // Secondary background
cx.theme().muted // Muted background
cx.theme().card // Card background
// Foreground colors
cx.theme().foreground // Primary text
cx.theme().muted_foreground // Muted text
// Semantic colors
cx.theme().primary // Primary accent
cx.theme().destructive // Danger/error
cx.theme().success // Success
cx.theme().warning // Warning
// Border colors
cx.theme().border // Default border
cx.theme().ring // Focus ring
Component Examples
Button Usage
use gpui_component::button::{Button, ButtonVariants};
Button::new("save")
.label("Save")
.icon(IconName::Save)
.primary()
.on_click(cx.listener(|this, _, window, cx| {
this.save(window, cx);
}))
Input with State
use gpui_component::input::{Input, InputState};
// Create state
let input_state = cx.new(|cx| InputState::new(cx));
// In render:
Input::new(&self.input_state)
.placeholder("Enter text...")
.cleanable(true)
PopupMenu / Command Palette
use gpui_component::menu::{PopupMenu, PopupMenuItem};
let menu = cx.new(|cx| {
PopupMenu::build(cx, |menu, window, cx| {
menu.menu_item(PopupMenuItem::new("New File")
.icon(IconName::FilePlus)
.action(Box::new(NewFile)))
.separator()
.menu_item(PopupMenuItem::new("Save")
.icon(IconName::Save)
.action(Box::new(Save)))
})
});
Completion Provider
use gpui_component::input::{CompletionProvider, InputState};
struct MyCompletionProvider;
impl CompletionProvider for MyCompletionProvider {
fn completions(
&self,
text: &Rope,
offset: usize,
trigger: CompletionContext,
window: &mut Window,
cx: &mut Context<InputState>,
) -> Task<Result<CompletionResponse>> {
let items = vec![
CompletionItem {
label: "option1".into(),
..Default::default()
},
];
Task::ready(Ok(CompletionResponse::Array(items)))
}
fn is_completion_trigger(
&self,
offset: usize,
new_text: &str,
cx: &mut Context<InputState>,
) -> bool {
new_text == "/" || new_text == "@"
}
}
Reference Files
For detailed patterns, read:
reference/components.md– Full component APIreference/theming.md– Theme system detailsreference/input-lsp.md– Input with completionsreference/menus.md– Menu and command palette
Project Setup
Cargo.toml
[dependencies]
gpui = "0.2"
gpui-component = { version = "0.4", features = ["webview"] }
Basic App Structure
use gpui::*;
use gpui_component::*;
struct App {
// state
}
impl Render for App {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
Root::new(
div()
.size_full()
.flex()
.flex_col()
.bg(cx.theme().background)
.child(self.render_toolbar(window, cx))
.child(self.render_content(window, cx)),
window,
cx
)
}
}
fn main() {
Application::new().run(|cx| {
gpui_component::init(cx);
cx.open_window(WindowOptions::default(), |window, cx| {
cx.new(|cx| App::new(cx))
});
});
}