Closes #1665 ## Description When `Input::new().font_family("font")` is used, the font hasn't been applied yet in `Input::render`, therefore the `text_wrapper` will calculate using the wrong font. This is why it's working when the font is added to the parent element. The fix moves the state update to `element` prepaint, where `window.text_style()` has the correct styles. The only downside is that there are now one additional state update. ## Screenshot | Before | After | | ---------------------------- | --------------------------- | | <img width="1125" height="246" alt="Screenshot From 2025-11-30 20-03-11" src="https://github.com/user-attachments/assets/1fa798a7-0b9c-4386-8940-ad5f6734b8a0" /> | <img width="1125" height="246" alt="Screenshot From 2025-11-30 20-00-23" src="https://github.com/user-attachments/assets/e970e7bc-1bfa-4a55-a342-3381d1684526" /> | ## How to Test Use some wide font, like `IBM Plex Mono`. Apply it to `Input::new(&some_state).font_family("IBM Plex Mono")` where the input state has `soft_wrap`. Here is a diff for `textarea_story.rs`. ```diff diff --git a/crates/story/src/textarea_story.rs b/crates/story/src/textarea_story.rs index f2c63d44..bd5cbb31 100644 --- a/crates/story/src/textarea_story.rs +++ b/crates/story/src/textarea_story.rs @@ -77,9 +77,9 @@ impl TextareaStory { let textarea_no_wrap = cx.new(|cx| { InputState::new(window, cx) - .multi_line(true) .rows(6) - .soft_wrap(false) + .multi_line(true) + .soft_wrap(true) .default_value("This is a very long line of text to test if the horizontal scrolling function is working properly, and it should not wrap automatically but display a horizontal scrollbar.\nThe second line is also very long text, used to test the horizontal scrolling effect under multiple lines, and you can input more content to test.\nThe third line: Here you can input other long text content that requires horizontal scrolling.\n") }); @@ -195,7 +185,7 @@ impl Render for TextareaStory { .child( section("Auto Grow") .max_w_md() - .child(Input::new(&self.textarea_auto_grow)), + .child(Input::new(&self.textarea_auto_grow).font_family("IBM Plex Mono")), ) .child( section("Auto Grow with No Wrap") ``` ## Checklist - [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and followed the guidelines. - [x] Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate. - [x] Passed `cargo run` for story tests related to the changes. - [ ] Tested macOS, Windows and Linux platforms performance (if the change is platform-specific) --------- Co-authored-by: Jason Lee <huacnlee@gmail.com> |
||
|---|---|---|
| .cargo | ||
| .github | ||
| crates | ||
| docs | ||
| examples | ||
| script | ||
| themes | ||
| .gitignore | ||
| .theme-schema.json | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CONTRIBUTING.md | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE-APACHE | ||
| README.md | ||
GPUI Component
UI components for building fantastic desktop applications using GPUI.
Features
- Richness: 60+ cross-platform desktop UI components.
- Native: Inspired by macOS and Windows controls, combined with shadcn/ui design for a modern experience.
- Ease of Use: Stateless
RenderOncecomponents, simple and user-friendly. - Customizable: Built-in
ThemeandThemeColor, supporting multi-theme and variable-based configurations. - Versatile: Supports sizes like
xs,sm,md, andlg. - Flexible Layout: Dock layout for panel arrangements, resizing, and freeform (Tiles) layouts.
- High Performance: Virtualized Table and List components for smooth large-data rendering.
- Content Rendering: Native support for Markdown and simple HTML.
- Charting: Built-in charts for visualizing your data.
- Editor: High performance code editor (support up to 200K lines) with LSP (diagnostics, completion, hover, etc).
- Syntax Highlighting: Syntax highlighting for editor and markdown components using Tree Sitter.
Showcase
Here is the first application: Longbridge Pro, built using GPUI Component.
Usage
gpui = "0.2.2"
gpui-component = "0.4.0"
Basic Example
use gpui::*;
use gpui_component::{button::*, *};
pub struct HelloWorld;
impl Render for HelloWorld {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div()
.v_flex()
.gap_2()
.size_full()
.items_center()
.justify_center()
.child("Hello, World!")
.child(
Button::new("ok")
.primary()
.label("Let's Go!")
.on_click(|_, _, _| println!("Clicked!")),
)
}
}
fn main() {
let app = Application::new();
app.run(move |cx| {
// This must be called before using any GPUI Component features.
gpui_component::init(cx);
cx.spawn(async move |cx| {
cx.open_window(WindowOptions::default(), |window, cx| {
let view = cx.new(|_| HelloWorld);
// This first level on the window, should be a Root.
cx.new(|cx| Root::new(view, window, cx))
})?;
Ok::<_, anyhow::Error>(())
})
.detach();
});
}
WebView
Still early and experimental; there are a lot of limitations.
GPUI Component has a WebView element based on Wry. This is an optional feature, which you can enable with a feature flag.
gpui-component = { version = "0.4.0", features = ["webview"] }
wry = { version = "0.53.3, package = "lb-wry" }
More usage examples can be found in the story directory.
Icons
GPUI Component has an Icon element, but it does not include SVG files by default.
The example uses Lucide icons, but you can use any icons you like. Just name the SVG files as defined in IconName. You can add any icons you need to your project.
Development
We have a gallery of applications built with GPUI Component.
cargo run
More examples can be found in the examples directory. You can run them with cargo run --example <example_name>.
Check out CONTRIBUTING.md for more details.
Compare to others
| Features | GPUI Component | Iced | egui | Qt 6 |
|---|---|---|---|---|
| Language | Rust | Rust | Rust | C++/QML |
| Core Render | GPUI | wgpu | wgpu | QT |
| License | Apache 2.0 | MIT | MIT/Apache 2.0 | Commercial/LGPL |
| Min Binary Size 1 | 12MB | 11MB | 5M | 20MB 2 |
| Cross-Platform | Yes | Yes | Yes | Yes |
| Documentation | Simple | Simple | Simple | Good |
| Web | No | Yes | Yes | Yes |
| UI Style | Modern | Basic | Basic | Basic |
| CJK Support | Yes | Yes | Bad | Yes |
| Chart | Yes | No | No | Yes |
| Table (Large dataset) | Yes (Virtual Rows, Columns) |
No | Yes (Virtual Rows) |
Yes (Virtual Rows, Columns) |
| Table Column Resize | Yes | No | Yes | Yes |
| Text base | Rope | COSMIC Text 3 | trait TextBuffer 4 | QTextDocument |
| CodeEditor | Simple | Simple | Simple | Basic API |
| Dock Layout | Yes | Yes | Yes | Yes |
| Syntax Highlight | Tree Sitter | Syntect | Syntect | QSyntaxHighlighter |
| Markdown Rendering | Yes | Yes | Basic | No |
| Markdown mix HTML | Yes | No | No | No |
| HTML Rendering | Basic | No | No | Basic |
| Text Selection | TextView | No | Any Label | Yes |
| Custom Theme | Yes | Yes | Yes | Yes |
| Built Themes | Yes | No | No | No |
| I18n | Yes | Yes | Yes | Yes |
Please submit an issue or PR if any mistakes or outdated are found.
License
Apache-2.0
-
Release builds by use simple hello world example. ↩︎
-
Iced Editor:
db5a1f6353/graphics/src/text/editor.rs (L65-L68)↩︎ -
egui TextBuffer:
0a81372cfd/crates/egui/src/widgets/text_edit/text_buffer.rs (L20)↩︎