All skills
lassejlv avatar

/build-gpui-apps

@52f4cfd
by Lasselassejlv/skills50 stars
1

Build, scaffold, refactor, debug, review, and validate native Rust desktop applications with GPUI. Recommend GPUI Kit and ask before adopting it; use gpui_kit imports after agreement, or preserve the chosen upstream GPUI stack. Includes the merged GPUI Kit component and design skills, full application/Base/Component/Shell documentation, coding and design guides, state, actions, async, input, accessibility, motion, themes, native integration, packaging, auto updates, testing, and production delivery. Use paper-to-gpui when the primary task is faithfully translating a selected Paper.design frame into an existing view.

Use this Skill: https://skilld.dev/gh/lassejlv/skills/build-gpui-apps

This session only. Nothing lands on disk.

referencesgpui-kitupstreamcomponentbutton.md

≈2.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Button

The Button element with multiple variants, sizes, and states. Supports icons, loading states, and can be grouped together.

Import

use gpui_kit::component::{
    Sizable as _,
    button::{Button, ButtonGroup, ButtonVariants as _},
};

Usage

The marked recipe below is a complete, Tested consumer recipe. The remaining examples are contextual fragments; keep the imports above when using variant or size builders.

<!-- recipe:command-control:start -->
use gpui_kit::IntoElement;
use gpui_kit::component::{
    Sizable as _,
    button::{Button, ButtonVariants as _},
};

pub fn primary_command() -> impl IntoElement {
    Button::new("save").primary().small().label("Save changes")
}
<!-- recipe:command-control:end -->

Basic Button

Button::new("my-button")
    .label("Click me")
    .on_click(|_, _, _| {
        println!("Button clicked!");
    })

Variants

use gpui_kit::component::button::ButtonVariants as _;

// Primary button
Button::new("btn-primary").primary().label("Primary")

// Secondary button (default)
Button::new("btn-secondary").label("Secondary")

// Danger button
Button::new("btn-danger").danger().label("Delete")

// Warning button
Button::new("btn-warning").warning().label("Warning")

// Success button
Button::new("btn-success").success().label("Success")

// Info button
Button::new("btn-info").info().label("Info")

// Ghost button
Button::new("btn-ghost").ghost().label("Ghost")

// Link button
Button::new("btn-link").link().label("Link")

// Text button
Button::new("btn-text").text().label("Text")

Outline Buttons

Outline style is not a variant itself, but can be combined with other variants.

use gpui_kit::component::button::ButtonVariants as _;

Button::new("btn").primary().outline().label("Primary Outline")
Button::new("btn").danger().outline().label("Danger Outline")

Compact Button

The compact method reduces the padding of the button for a more condensed appearance.

// Compact (reduced padding)
Button::new("btn")
    .label("Compact")
    .compact()

Sizeable

The Button supports the Sizable trait for different sizes.

use gpui_kit::component::Sizable as _;

Button::new("btn").xsmall().label("Extra Small")
Button::new("btn").small().label("Small")
Button::new("btn").label("Medium") // default
Button::new("btn").large().label("Large")

With Icons

The icon method supports multiple types, allowing you to use different visual indicators:

  • Icon / IconName - Static icons for actions and visual cues
  • Spinner - Animated loading indicator for async operations
  • ProgressCircle - Circular progress indicator showing completion percentage

All icon types automatically adapt to the button's size and can be customized with colors and other properties.

Icon Types
use gpui_kit::component::{Icon, IconName};

// Using IconName (simplest)
Button::new("btn")
    .icon(IconName::Check)
    .label("Confirm")

// Using Icon with custom size
Button::new("btn")
    .icon(Icon::new(IconName::Heart))
    .label("Like")

// Icon only (no label)
Button::new("btn")
    .icon(IconName::Search)
Spinner Icon

Use a Spinner to indicate loading or processing state:

use gpui_kit::component::{ActiveTheme as _, spinner::Spinner};

// Basic spinner
Button::new("btn")
    .icon(Spinner::new())
    .label("Loading...")

// Spinner with custom color
Button::new("btn")
    .icon(Spinner::new().color(cx.theme().blue))
    .label("Processing")

// Spinner with icon
Button::new("btn")
    .icon(Spinner::new().icon(IconName::LoaderCircle))
    .label("Syncing")
ProgressCircle Icon

Use a ProgressCircle to show progress percentage:

use gpui_kit::component::{
    ActiveTheme as _, Sizable as _,
    button::ButtonVariants as _,
    progress::ProgressCircle,
};

// Basic progress circle
Button::new("btn")
    .icon(ProgressCircle::new("install-progress").value(45.0))
    .label("Installing...")

// Progress circle with custom color
Button::new("btn")
    .primary()
    .icon(
        ProgressCircle::new("download-progress")
            .value(75.0)
            .color(cx.theme().primary_foreground)
    )
    .label("Downloading")

// Different sizes
Button::new("btn")
    .small()
    .icon(ProgressCircle::new("progress-1").value(60.0))
    .label("Installing...")

Button::new("btn")
    .large()
    .icon(ProgressCircle::new("progress-2").value(80.0))
    .label("Installing...")
Dynamic Icon Updates

Icons can be updated dynamically based on component state:

struct InstallButton {
    progress: f32,
    is_installing: bool,
}

impl InstallButton {
    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        let button = Button::new("install-btn")
            .label(if self.is_installing {
                "Installing..."
            } else {
                "Install"
            });

        if self.is_installing {
            button.icon(
                ProgressCircle::new("install-progress")
                    .value(self.progress)
            )
        } else {
            button.icon(IconName::Download)
        }
    }
}
Loading State with Icons

When a button is in loading state, it automatically handles icon transitions:

// If icon is already a Spinner or ProgressCircle, it will be shown during loading
Button::new("btn")
    .icon(Spinner::new())
    .label("Processing")
    .loading(true) // Spinner will continue to show

// If icon is a regular Icon, it will be replaced with a Spinner during loading
Button::new("btn")
    .icon(IconName::Save)
    .label("Saving")
    .loading(true) // Icon will be replaced with Spinner

With a dropdown caret icon

The .dropdown_caret method can allows adding a dropdown caret icon to end of the button.

Button::new("btn")
    .label("Options")
    .dropdown_caret(true)

Button States

There have disabled, loading, selected state for buttons to indicate different statuses.

use gpui_kit::component::{Disableable as _, Selectable as _};

// Disabled
Button::new("btn")
    .label("Disabled")
    .disabled(true)

// Loading
Button::new("btn")
    .label("Loading")
    .loading(true)

// Selected
Button::new("btn")
    .label("Selected")
    .selected(true)

Button Group

ButtonGroup::new("btn-group")
    .child(Button::new("btn1").label("One"))
    .child(Button::new("btn2").label("Two"))
    .child(Button::new("btn3").label("Three"))

Toggle Button Group

use gpui_kit::component::Selectable as _;

ButtonGroup::new("toggle-group")
    .multiple(true) // Allow multiple selections
    .child(Button::new("btn1").label("Option 1").selected(true))
    .child(Button::new("btn2").label("Option 2"))
    .child(Button::new("btn3").label("Option 3"))
    .on_click(|selected_indices, _, _| {
        println!("Selected: {:?}", selected_indices);
    })

Custom Variant

use gpui_kit::component::{
    ActiveTheme as _, Colorize as _,
    button::{ButtonCustomVariant, ButtonVariants as _},
};

let custom = ButtonCustomVariant::new(cx)
    .color(cx.theme().magenta)
    .foreground(cx.theme().primary_foreground)
    .hover(cx.theme().magenta.opacity(0.1))
    .active(cx.theme().magenta);

Button::new("custom-btn")
    .custom(custom)
    .label("Custom Button")

API Reference

Examples

With Tooltip

Button::new("btn")
    .label("Hover me")
    .tooltip("This is a helpful tooltip")
    .tooltip_placement(Placement::Bottom)

Use .tooltip_placement(...) to prefer a side for either .tooltip(...) or .tooltip_with_action(...). The tooltip still flips when that side does not fit. Omit placement to keep automatic positioning.

Custom Children

Button::new("btn")
    .child(
        h_flex()
            .items_center()
            .gap_2()
            .child("Custom Content")
            .child(IconName::ChevronDown)
            .child(IconName::Eye)
    )

Documentation license: original prose and illustrations for which GPUI Kit holds licensing rights are also offered under CC BY 4.0. When copying or adapting, credit GPUI Kit, link the source (https://gpui-kit.com/component/button) and https://creativecommons.org/licenses/by/4.0/, and indicate changes. Code examples and software source use Apache-2.0; third-party material retains its terms; existing Apache-2.0 permissions remain.

Bundled from GPUI Kit. Documentation prose: CC BY 4.0; code examples: Apache-2.0. Changes: documentation links localized, asset URLs made absolute, and this attribution added.

Source: SKILL.md on GitHub

No alertstoday3 checks · Risk SAFE
  • Gen Agent Trust Hubtoday

    The skill is a comprehensive development toolkit for building native Rust desktop applications with the GPUI framework. It provides a reference application, extensive documentation, and maintenance scripts. No malicious patterns were identified. The skill has a low-risk profile typical of developer tools that process and execute external codebases.

  • Sockettoday

    No alerts

  • Snyktoday

    Risk: LOW · No issues

Signed by skilld at 52f4cfd. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 4 days ago

README badge

README badge for lassejlv/skills/build-gpui-apps