
gpui-elements
UI element creation and composition with GPUI. Use when building element trees, creating custom components, implementing layouts, or working with conditional rendering.
UI element creation and composition with GPUI. Use when building element trees, creating custom components, implementing layouts, or working with conditional rendering.
GPUI Elements
This skill covers creating and composing UI elements in GPUI applications.
Overview
Elements are the building blocks of GPUI UIs:
- Built with
div()as the base element - Styled with chainable methods
- Composed with
.child()and.children() - Support conditional rendering with
.when() - Use flexbox for layout
Basic Element Creation
div() Element
use gpui::*;
impl Render for MyView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.child("Hello, GPUI!")
}
}
Adding Children
div()
.child("First child")
.child(
div()
.child("Nested child")
)
.child("Third child")
Multiple Children with Vector
let items = vec!["One", "Two", "Three"];
div().children(
items.into_iter().map(|text| {
div().child(text)
})
)
Text Elements
String Types
use gpui::*;
impl Render for MyView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
// &str
.child("Static text")
// String
.child(format!("Count: {}", self.count))
// SharedString (most efficient)
.child(self.title.clone())
}
}
SharedString
use gpui::*;
struct MyView {
title: SharedString,
}
impl MyView {
fn new() -> Self {
Self {
title: "Default Title".into(),
}
}
fn set_title(&mut self, title: impl Into<SharedString>) {
self.title = title.into();
}
}
// SharedString implements IntoElement
impl Render for MyView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().child(self.title.clone())
}
}
Conditional Rendering
when() Method
div()
.when(condition, |this| {
this.bg(rgb(0x3b82f6))
.child("Condition is true")
})
when_some() for Options
div()
.when_some(maybe_text, |this, text| {
this.child(text)
})
Practical Example
struct MyView {
is_active: bool,
error: Option<String>,
}
impl Render for MyView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.when(self.is_active, |this| {
this.bg(rgb(0x22c55e))
})
.when_some(self.error.clone(), |this, error| {
this.child(
div()
.p_2()
.bg(rgb(0xef4444))
.text_color(rgb(0xffffff))
.child(error)
)
})
}
}
Custom Components
RenderOnce Components
use gpui::*;
#[derive(IntoElement)]
struct Button {
label: SharedString,
on_click: Option<Box<dyn Fn(&mut App) + 'static>>,
}
impl Button {
fn new(label: impl Into<SharedString>) -> Self {
Self {
label: label.into(),
on_click: None,
}
}
fn on_click(mut self, handler: impl Fn(&mut App) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
}
}
impl RenderOnce for Button {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let mut element = div()
.px_4()
.py_2()
.bg(rgb(0x3b82f6))
.text_color(rgb(0xffffff))
.rounded(px(6.0))
.cursor_pointer()
.child(self.label);
if let Some(handler) = self.on_click {
element = element.on_click(move |_event, _window, cx| {
handler(cx);
});
}
element
}
}
// Usage
impl Render for MyView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().child(
Button::new("Click Me")
.on_click(|cx| {
println!("Button clicked!");
})
)
}
}
Render Components
struct Card {
title: SharedString,
content: SharedString,
}
impl Render for Card {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.p_4()
.bg(rgb(0x1a1a1a))
.rounded(px(8.0))
.flex()
.flex_col()
.gap_2()
.child(
div()
.text_lg()
.font_bold()
.child(self.title.clone())
)
.child(
div()
.text_sm()
.child(self.content.clone())
)
}
}
Layout Patterns
Vertical Stack
div()
.flex()
.flex_col()
.gap_4()
.child("Item 1")
.child("Item 2")
.child("Item 3")
Horizontal Row
div()
.flex()
.flex_row()
.gap_4()
.items_center()
.child("Left")
.child("Center")
.child("Right")
Grid-like Layout
div()
.flex()
.flex_wrap()
.gap_4()
.children((0..12).map(|i| {
div()
.w(px(100.0))
.h(px(100.0))
.bg(rgb(0x3b82f6))
.child(format!("Item {}", i))
}))
Centering
div()
.flex()
.items_center()
.justify_center()
.size_full()
.child("Centered content")
Dynamic Lists
Simple List
struct ListView {
items: Vec<String>,
}
impl Render for ListView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
.gap_2()
.children(
self.items.iter().map(|item| {
div()
.p_2()
.bg(rgb(0x1a1a1a))
.rounded(px(4.0))
.child(item.clone())
})
)
}
}
List with Index
div()
.children(
self.items.iter().enumerate().map(|(i, item)| {
div()
.child(format!("{}. {}", i + 1, item))
})
)
Nested Components
Component Composition
struct Header;
impl Render for Header {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.h(px(64.0))
.bg(rgb(0x1a1a1a))
.child("Header")
}
}
struct Sidebar;
impl Render for Sidebar {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.w(px(250.0))
.bg(rgb(0x2a2a2a))
.child("Sidebar")
}
}
struct AppLayout {
header: Entity<Header>,
sidebar: Entity<Sidebar>,
}
impl Render for AppLayout {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
.flex_col()
.child(self.header.clone())
.child(
div()
.flex()
.flex_1()
.child(self.sidebar.clone())
.child(
div()
.flex_1()
.child("Main content")
)
)
}
}
Element Patterns
Clickable Card
div()
.p_4()
.bg(rgb(0x1a1a1a))
.rounded(px(8.0))
.cursor_pointer()
.hover(|style| style.bg(rgb(0x2a2a2a)))
.on_click(|_event, _window, cx| {
println!("Card clicked");
})
.child("Click me")
Input Field
struct InputField {
value: SharedString,
}
impl Render for InputField {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.px_3()
.py_2()
.bg(rgb(0x1a1a1a))
.border_1()
.border_color(rgb(0x4a4a4a))
.rounded(px(4.0))
.child(self.value.clone())
.on_click(cx.listener(|this, _event, _window, cx| {
// Handle focus
}))
}
}
Toggle Switch
struct Toggle {
enabled: bool,
}
impl Render for Toggle {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.w(px(44.0))
.h(px(24.0))
.rounded(px(12.0))
.bg(if self.enabled {
rgb(0x22c55e)
} else {
rgb(0x4a4a4a)
})
.cursor_pointer()
.on_click(cx.listener(|this, _event, _window, cx| {
this.enabled = !this.enabled;
cx.notify();
}))
}
}
Best Practices
- Use SharedString for text: Avoids unnecessary string copies
- Use .when() for conditions: More readable than if/else in render
- Extract reusable components: Create RenderOnce components for common patterns
- Keep render pure: Don't mutate state directly in render() method
- Use children() for lists: More efficient than multiple .child() calls
- Chain methods: Build elements with method chaining for clarity
Common Mistakes
| Mistake | Problem | Solution |
|---|---|---|
| Mutating state in render | Race conditions | Use event handlers to mutate |
| Not using SharedString | Extra allocations | Use SharedString for text |
| Deep nesting | Hard to read | Extract into components |
| Missing IntoElement | Compile error | Ensure types implement IntoElement |
| Forgetting .clone() | Borrow errors | Clone SharedString when using multiple times |
Summary
- Use
div()as the base element - Add children with
.child()or.children() - Use
.when()for conditional rendering - Create components with
RenderOnceorRender - Use
SharedStringfor efficient text handling - Compose with flexbox layout methods
References
You Might Also Like
Related Skills

cache-components
Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.
vercel
component-refactoring
Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component --json` shows complexity > 50 or lineCount > 300, when the user asks for code splitting, hook extraction, or complexity reduction, or when `pnpm analyze-component` warns to refactor before testing; avoid for simple/well-structured components, third-party wrappers, or when the user explicitly wants testing without refactoring.
langgenius
web-artifacts-builder
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.
anthropics
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
anthropics
react-modernization
Upgrade React applications to latest versions, migrate from class components to hooks, and adopt concurrent features. Use when modernizing React codebases, migrating to React Hooks, or upgrading to latest React versions.
wshobson
tailwind-design-system
Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
wshobson