gpui-base
gpui-base is the reusable foundation of the GPUI Component Rust desktop application framework, built on GPUI. It is intended for applications that want to build and own their own design systems. It provides interaction behavior, focus management, accessibility semantics, animation, virtual lists, theme tokens, and other foundational capabilities without imposing a visual style.
Use
gpui-componentif you want ready-to-use components with a complete visual design. Usegpui-baseif your application should own its component source and visual styles while reusing stable, shared behavior.
Where It Fits in GPUI Component
GPUI Component is the framework and project brand. Its currently implemented architecture has two directly usable layers:
application
├── gpui-component Complete, styled framework experience
└── custom UI Application-owned design system
└── gpui-base Interaction, state, and infrastructure (this crate)
Dependencies always point from higher layers toward the foundation: gpui-base does not depend on gpui-component. Existing applications can continue using gpui-component; a direct dependency on gpui-base is only necessary when building custom components or a design system.
Relationship to the shadcn Ecosystem
The GPUI Component ecosystem follows the same layering idea as shadcn:
| GPUI ecosystem | shadcn ecosystem |
|---|---|
| GPUI | HTML + Tailwind CSS |
gpui-base |
Base UI |
gpui-component |
shadcn |
crates/component in GPUI Component |
shadcn's default UI |
Design Principles
- Behavior belongs to the foundation: click handling, keyboard activation, controlled state, focus, accessibility roles, and infrastructure.
- Presentation belongs to the application: layout, size, color, spacing, radius, borders, shadows, variants, and animation are defined by the application or a higher-level component.
- Applications own their components: foundation controls can be freely composed and modified without adopting a fixed visual language.
- Semantic APIs come first: themes expose tokens such as
primary,surface, anddestructiveinstead of accumulating component-specific fields. - GPUI-native composition: controls implement GPUI interfaces such as
StyledandParentElementand work with GPUI's fluent builder API.
For example, Button::new("save") has no padding, background, radius, or size by default. Being unstyled is an explicit API contract, not a missing feature.
Installation
Depend on gpui-kit, which pins the GPUI crates gpui-base was built
against and re-exports them as gpui_kit::gpui and gpui_kit::platform, with
gpui-base itself always available at gpui_kit::base. Turn off the default
features to skip the styled layers:
[]
= { = "0.6", = false }
If Cargo reports incompatible GPUI types, check whether your application pulls
GPUI in from somewhere other than gpui-kit.
Optional Features
| Feature | Enabled by default | Purpose |
|---|---|---|
inspector |
No | Enables inspector support in both gpui and gpui_macros |
Initialization
Call gpui_kit::base::init(cx) once before creating windows or using foundation controls. It installs the global theme and focus-trap infrastructure required by the base layer.
use *;
If the application already calls gpui_kit::init(cx), do not call gpui_kit::base::init(cx) again. The higher-level initializer includes base initialization.
Quick Start
Foundation controls can be styled and given children like ordinary GPUI elements:
use *;
use ;
use Button;
;
An ElementId must remain stable within a view so GPUI can preserve focus and element state. Button handles pointer, Enter, and Space activation through one path and provides disabled, selected, tab_index, and tab_stop for semantic state and focus traversal.
Controlled State
Checkbox, Radio, Switch, and Toggle are controlled components. Their callbacks report the next value; the application updates its own state and passes that value back on the next render:
use *;
use ;
use ;
The caller also defines how semantic states look. For example:
new
.selected
.disabled
.styles
.child
Semantic state styles express states such as checked, pressed, selected, indeterminate, and disabled. Every control resolves its final style in one fixed order:
- the style applied directly in the main builder chain,
- value states such as
checked,pressed,selected, orfocused, disabled, which is always resolved last.
Semantic states therefore layer over the builder chain, the same way GPUI layers hover, active, and focus_visible on top of an element's base style. A state only overrides the fields it sets, so unrelated builder-chain styles are preserved. To keep a specific builder-chain style as the closest layer even while a state is active, replay it inside that state:
new
.bg
.styles
Base controls cannot suppress hover or active styles while disabled, because GPUI does not expose those refinements. Guard them at the call site with when(!disabled, ..).
Capability Overview
Unstyled Controls
| API | Behavior provided |
|---|---|
Button |
Click and keyboard activation, focus, disabled and selected states, and the Button accessibility role |
Checkbox / CheckboxIndicator |
Checked, unchecked, and indeterminate states with corresponding accessibility semantics |
Radio / RadioGroup |
Radio activation, focus, and a grouping container |
Switch / SwitchTrack / SwitchThumb |
A controlled switch with independently styled track and thumb parts |
Toggle / ToggleGroup |
A controlled pressed state and grouping container |
Link |
Link semantics and activation with an application-provided open_with navigation strategy |
Table and semantic table parts |
Table, row-group, row, column-header, cell roles, and accessibility indices without layout or styling |
Toast / ToastStack / ToastManager |
Alert semantics, lifecycle, timers, limits, measured stack geometry, and interaction-aware motion |
Text Editing
Text editing is split into purpose-specific controls instead of exposing the complete editor interface on every text field:
| Control | State | Use |
|---|---|---|
Input |
InputState |
Single-line values, masking, validation, and number stepping |
Textarea |
TextareaState |
Ordinary multi-line text, fixed rows, wrapping, and auto-grow |
Editor |
EditorState |
Source code, highlighting, gutter, folding, decorations, diagnostics, and LSP integration |
All three share the internal InputBaseState editing engine. Applications
should construct the purpose-specific state rather than configuring modes on
the shared engine.
The base layer never opens a URL by itself. This allows the same Link to target internal routing, an embedded web view, or the system browser.
Focus and Interaction
FocusTrapElementturns an interactive element into a focus trap. Tab and Shift-Tab cycle within the container.active_focus_trapreturns the active focus trap for a window.InteractiveElementExtadds interaction helpers to GPUI interactive elements.ElementExtadds post-layout, prepaint observation to parent elements.FocusableExtdraws a focus ring using the application theme.
Scrolling and Large Data Sets
ScrollbarsupportsScrollHandle,UniformListScrollHandle,ListState, andVirtualListScrollHandle, with vertical, horizontal, and dual-axis modes.ScrollbarModecontrols when a scrollbar is visible.v_virtual_listandh_virtual_listrender only the visible range while allowing every item to have a different size.VirtualListScrollHandlereads or updates a virtual list's scroll position.AutoScrollprovides timer-based edge scrolling during drag interactions.
A virtual list requires the caller to provide item sizes. Vertical lists use each item's height, while horizontal lists use each item's width. Unlike GPUI's uniform_list, this is suitable for data whose rows or columns do not share one size.
Animation
gpui-base provides two animation APIs:
motion::transitionis the preferred value-transition API. The caller chooses the animated property; it supports duration, delay, custom easing, smooth target reversal, and reduced-motion preferences.animation::Transitionis the legacy element-animation API for composing fade, slide, and size effects.
Foundation controls do not install animation automatically. Applications choose animation properties and timing according to their own visual language.
See the Motion guide and run its five focused interactive demonstrations with:
Themes and Styles
Themestores base-layer global configuration, including semantic tokens and scrollbar defaults.SemanticThemeTokenscontainscolors,radius,spacing,typography, andshadowscales.StateStyleis a semantic-state style builder compatible with fluent helpers such aswhenandwhen_some.StyledExtprovides common helpers for horizontal and vertical flex layouts, margins and padding, font weights, focus styling, and debug outlines.h_flex,v_flex, andbox_shadoware common element and style constructors.
The global base theme can be customized after initialization:
use ;
use Theme;
let theme = global_mut;
theme.tokens.colors.primary = rgb.into;
theme.tokens.radius.md = px;
Tokens describe design semantics; they do not automatically style unstyled controls. Applications read and apply these tokens in their own component implementations.
General Data and Layout Utilities
| API | Purpose |
|---|---|
History |
Browser-style navigation trail with back and forward entries |
UndoHistory |
Grouped undo and redo transactions |
SliderState |
Single or range values, linear or logarithmic scales, and slider events |
IndexPath |
A section, row, and column index path |
Placement / Side |
Placement and layout direction descriptions |
AxisExt / LengthExt / Edges |
GPUI geometry extensions and serializable edges |
Relationship to gpui-component
The crates target different abstraction levels and can be used in the same application:
gpui-base |
gpui-component |
|
|---|---|---|
| Role | Behavior and infrastructure | Complete UI component library |
| Default presentation | None | Included |
| Visual style owner | Application | Component library, customizable through its Theme and APIs |
| Best suited for | Custom design systems, registry components, and foundation reuse | Building complete desktop applications quickly |
| Initialization | gpui_kit::base::init(cx) |
gpui_kit::init(cx), which includes base initialization |
Do not migrate from gpui-component by mechanically replacing imports. For example, gpui_kit::component::button::Button is a fully styled higher-level component, while gpui_kit::base::Button requires the caller to provide its children and all presentation styles.
Platform Support
Platform support follows GPUI and GPUI Component:
- macOS on Apple Silicon and Intel
- Linux on x86_64
- Windows on x86_64
- WebAssembly support depends on the APIs in use and the GPUI Web runtime
Development and Verification
Run these commands from the GPUI Component repository root:
# Check the foundation crate
# Run the foundation crate tests
# Check formatting
# Run Clippy
The current Rust interface is defined by the source code and generated API
documentation. See ../../docs/ARCHITECTURE.md
for the source-derived module architecture and
../../docs/STYLING-AND-MOTION.md for the
style and motion contracts.
Related Resources
- GPUI Kit repository
- GPUI Kit documentation
gpui-componentcrategpui-baseAPI documentation- GPUI
- Contributing guide
License
Apache-2.0. See ../../LICENSE-APACHE.