Claude-skill-registry gpui-components
Generates Rust code for GPUI desktop UI components following Zed editor patterns. Use when building desktop applications with gpui crate, creating themed UI components, implementing autocomplete/completions, building command palettes, or working with the gpui-component library. Covers RenderOnce components, Entity state management, theming with ActiveTheme, and Zed-style UI patterns.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/gpui-components" ~/.claude/skills/majiayu000-claude-skill-registry-gpui-components && rm -rf "$T"
manifest:
skills/data/gpui-components/SKILL.mdsource content
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
orRenderOnce
traitsRender - Implementing themed components with
ActiveTheme - Building autocomplete/completion menus
- Creating command palettes and popup menus
- Working with
crategpui-component
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
- Buttons with variants (primary, danger, ghost, link)Button
- Text input with LSP completion supportInput
- Numeric input with step controlsNumberInput
- Checkbox with labelCheckbox
- Toggle switchSwitch
- Radio button groupsRadio
- Dropdown selectSelect
- Range sliderSlider
Layout Components
- Modal dialogsDialog
- Popup popoversPopover
/Menu
- Menus and context menusPopupMenu
- Tab navigationTab
- Collapsible sectionsAccordion
- Sidebar navigationSidebar
- Dockable panelsDock
Display Components
- Status badgesBadge
- User avatarsAvatar
- Icon display (IconName enum)Icon
- Text labelsLabel
- TooltipsTooltip
- Toast notificationsNotification
Data Components
- Data tablesTable
/List
- Scrollable listsVirtualList
- Tree viewTree
- Charts and plotsChart
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:
- Full component APIreference/components.md
- Theme system detailsreference/theming.md
- Input with completionsreference/input-lsp.md
- Menu and command palettereference/menus.md
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)) }); }); }