guise
Native UI · built on Zed's gpui

Native UI for Rust.
Write it, or draw it.

guise is a batteries-included component layer for gpui — a themed palette, sizing tokens, and over a hundred and thirty composable components, GPU-rendered at native speed. Tailor is the drag-and-drop builder for it, in the same repository: it lays those same components out on a canvas and hands back the Rust.

guise-ui = "1.5"
Tailor the builder

Drag real components onto a canvas, wire the state and the actions, and export.

guise the components

Rust you own, with no dependency on Tailor left in it — or write it by hand from the start.

The palette — 14 open-color hues, 10 shades each, read straight from the theme.

Everything you need to build a desktop app.

A complete component layer, not a widget grab-bag — themed, composable, and native from the first line.

Themed palette

A 14-hue open-color palette, sizing tokens, and semantic colors. Read every value from the theme — light / dark switching is free.

Builder API

Chainable builders that read the same on every component: .variant(), .color(), .size(), .radius().

Stateful entities

Inputs, overlays and data views are gpui entities that own their state and emit events you take with cx.subscribe.

Flex + macros

A Flutter-style flexbox layer plus terse row! / col! / zstack! macros for dense layout.

Reactive state

A lightweight React-style layer: Signal, use_state, provide / use_context, and use_form validation.

Native WebView

Embed a real OS web view (WKWebView / WebView2 / WebKitGTK) via wry, positioned inside normal guise layout.

Lucide icons built in

Every Lucide icon as an IconName variant, drawn from an embedded icon font — no asset pipeline, tinted and sized like text.

◫︎

An inspector in the box

DevTools shaped like Safari's Web Inspector — an element tree your components record themselves, the box model, resolved styles with the line each came from, plus logs, network and timelines the host feeds.

Self-update included

Check a release feed, install the new version in place — rsync onto the .app, rename over the AppImage — verify its signature, and restart. Prompt included.

A builder in the box

Tailor lays these components out on a canvas and writes the Rust — an interface builder that ships in the same repository as the library it draws with.

Data views that scale

TableView, DataView, TreeView and VirtualList window their rows — a hundred thousand of them render as cheaply as twenty.

Two patterns, and you know the whole library.

Controlled widgets take a value and a handler. Stateful ones are entities you create with cx.new and subscribe to. Same mental model — native rendering underneath.

Read the component model →
  • Variant + color + size on every component
  • Events via cx.subscribe, redraws via cx.notify
  • No hardcoded colors or spacing — only theme tokens
  • Drop to the flex layer or macros when you want them
text.rs
// a stateful entity: owns its buffer, emits events
let name = cx.new(|cx| {
    TextInput::new(cx)
        .label("Name")
        .placeholder("guise-app")
});

cx.subscribe(&name, |this, _input, e: &TextInputEvent, cx| {
    if let TextInputEvent::Change(value) = e {
        this.name = value.clone();
        cx.notify();
    }
})
.detach();

Over 130 components, one palette.

From buttons to a native web view, a code editor and an AI chat kit — a selection of the families below.

TextInput Button · variant Badge Switch Alert

One window, seven components, every value read from the theme.

01 Button variant · color · size docs →
Framework
gpui
02 Inputs TextInput · Select docs →
Sync
I agree
03 Controls Switch · Checkbox · Slider docs →
SavedAll changes synced.
04 Feedback Alert · Progress · Loader docs →
OverviewActivityMembers
WCADJR+3
05 Data Tabs · AvatarGroup docs →
ActionsDuplicateRenameDelete
06 Overlays Menu · Popover · Modal docs →
See every component in the gallery →

Systems, not just widgets.

Layout, motion and state — the parts of an app a component grab-bag leaves out.

See them all in one app — the data workbench tutorial →

Draw the interface. Keep the Rust.

Tailor is a drag-and-drop builder for guise, shipped in the same repository and downloadable as an app. Its canvas renders the real components against the real theme — there is no second drawing to keep in step — so what you lay out is what it generates, and what it generates is a file you own.

Read about Tailor →
dashboard_screen.rs
//! DashboardScreen — generated by Tailor from Dashboard.
//! …take this file and own it; it has no dependency on Tailor.

use gpui::prelude::*;
use guise::prelude::*;
use super::StatCard;

impl Render for DashboardScreen {
    fn render(&mut self, …) -> impl IntoElement {
        AppShell::new()
            .child(
                div()
                    .flex()
                    .flex_col()
                    .gap(px(20.))
                    .p(px(24.))
                    .child(
                        div()
                            .flex_row()
                            .gap(px(16.))
                            .child(StatCard::new())
                            .child(StatCard::new())
                    )
            )
    }
}

Ready to get started?

Add the dependency and open your first window.

guise-ui = "1.5"