Closes [1729](https://github.com/longbridge/gpui-component/issues/1729)
## Description
Adds support for inline completions, which allows the editor to support
agentic "tab to complete" solutions. This works, (tested macOS), but not
sure of any gotchas or different approaches.
## Screenshot
https://github.com/user-attachments/assets/8e437f1e-9792-4417-b070-0a1dd8de6024
## How to Test
User implements the `inline_completion` method in CompletionsProvider.
Not implementing should have no effect.
## 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>
## Description
When using `set_value` with a `code_editor("lang").multi_line(false)`
the highlighting and lsp will not be reset.
## Video
### Before
https://github.com/user-attachments/assets/5fef5b6e-478e-4233-a911-e087f889040a
### After
https://github.com/user-attachments/assets/3ea99060-8dba-4604-9d3f-c151b3aadcf2
## How to Test
`cargo run --release -- input`, enter some text in "Single line code
editor", click "Reset"
## 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)
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>
## Description
This PR fixes an issue where the editor's "reverse cursor" state was not
reset
after completing a text selection. Because the flag remained `true`, the
cursor
could appear on the wrong side of the selection when the next
interaction
started.
## Screenshot
| Before | After |
|--------|--------|
| <video
src="https://github.com/user-attachments/assets/308c5119-52da-4bdb-9a94-36617d957c63"
controls width="360"></video> | <video
src="https://github.com/user-attachments/assets/bf9328b4-96d8-48df-9cc0-99fccaced7c5"
controls width="360"></video> |
## How to Test
`cargo run --example editor`
## Checklist
- [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and
followed the guidelines.
- [ ] 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)
## Screenshot
From `input_story`:
<img width="1069" height="122" alt="Screenshot From 2025-11-28 09-14-03"
src="https://github.com/user-attachments/assets/f14ef2fc-4939-4ceb-be3e-bede492f8602"
/>
## Breaking Changes
- `.multi_line()` was changed to `.multi_line(bool)`.
- Removed pub `InputMode`, this should only for internal.
```diff
InputState::new(window, cx)
- .multi_line()
+ .multi_line(true)
```
## 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)
Use cases,
1) In my API client, I have a tree sitter language for the URL input,
<img width="1001" height="162" alt="Image"
src="https://github.com/user-attachments/assets/9771decf-b0b7-4230-8ed6-784a95b72af1"
/>
2) In my SQL editor I want to be able to allow JSON syntax highlighting
for inline editing of json columns,
<img width="501" height="130" alt="Image"
src="https://github.com/user-attachments/assets/f0f879cc-841f-49d2-a23a-2effc3747f38"
/>
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
## Description
1. Add `overflow_scrollbar`, `overflow_y_scrollbar`, `overflow_x_scroll`
to GPUI elements to let them has scrollbars. It is almost like the
`overscroll` but adds the Scrollbar.
2. And adjust the display scrollbar of margining 4px of the container.
3. Add `scrollbar`, `vertical_scrollbar`, `horizontal_scrollbar` with
your own scroll handle.
<img width="1181" height="911" alt="image"
src="https://github.com/user-attachments/assets/8b02cd54-d527-4f22-b9be-f762ede22122"
/>
## Break Changes
- There `Scrollable` trait and it `scrollable` method has been removed.
```diff
- div().id("contents").scrollable(Axis::Vertical)
+ div().id("contents").overflow_y_scrollbar()
```
This PR to improve the Scrollbar API to manage the state in the
internal.
## Break Changes
Describe any breaking changes introduced by this pull request. If none,
remove this section.
- Removed `scrollbar_state` argument from `Scrollbar::new`,
`Scrollbar::both`, `Scrollbar::vertical` and `Scrollbar::horizontal`.
```diff
- Scrollbar::horizontal(&self.scrollbar_state, &self.scroll_handle)
+ Scrollbar::horizontal(&self.scroll_handle)
- Scrollbar::vertical(&self.scrollbar_state, &self.scroll_handle)
+ Scrollbar::vertical(&self.scroll_handle)
```
- Change `struct ScrollbarState` to private, we not need this not.
```diff
- pub struct ScrollbarState {
+ struct ScrollbarState {
```
- Renamed `trait ScrollHandleOffsetable` to `trait ScrollbarHanle`.
```diff
- pub trait ScrollHandleOffsetable {
+ pub trait ScrollbarHanle {
```
- Removed `Scrollbar::both`, now use `Scrollbar::new` instead.
```diff
- Scrollbar::both(&scroll_handle)
+ Scrollbar::new(&scroll_handle)
```
Fixes#1562
## Problem
Single-line input fields were blocking all scroll wheel events,
preventing parent containers from handling vertical page scrolling.
## Solution
- Check if input is in single-line mode and scroll is purely vertical
- Allow vertical scroll events to propagate in single-line mode
- Only stop propagation when scroll offset actually changes
## Behavior
- Single-line inputs: vertical scroll passes through to parent
- Multi-line inputs: all scroll behavior unchanged
- Horizontal scrolling still works in both modes
https://github.com/longbridge/gpui-component/pull/1502#issuecomment-3485354324
## Break Change
- The `DatePicker` and `Select` has changed `cleanable` default from
`true` to `false`.
- Updated `Input`, `DatePicker` and `Select` the `cleanable` to have a
argument.
```diff
- pub fn cleanable(mut self)
+ pub fn cleanable(mut self, cleanable: bool)
```
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
## Break Change
- Removed `set_query_input`, `query_input` and `no_query` method from
List. Now use `List::new(&state).searchable(false)` to intead of
`no_query`.
- Removed `searchable` method from `SelectDelegate`, use
`Select::searchable` instead.
In most applications, when text is selected and backspace/delete is
pressed, the selection is simply deleted.
Currently, gpui-component will ignore the selected text and delete the
previous/next word when Ctrl is pressed.
This can be very confusing especially if you do ctrl+a then
ctrl+backspace, expecting the input to be cleared.
This PR makes it so that if there is an active selection, the active
selection is deleted before doing any extra processing.
## Break Change
- Like Select, Input API design, now `List`, `Table` also has ListState
and TableState.
```diff
- let table = cx.new(|_| Table::new(delegate, window, cx).stripe(true).border(true))
+ let table = cx.new(|_| TableState::new(delegate, window, cx))
+ Table::new(&table).stripe(true).border(true) // for render
- let list = cx.new(|_| List::new(delegate, window, cx))
+ let list = cx.new(|_| ListState::new(delegate, window, cx))
+ List::new(&list) // for render
```
- ListDelegate, TableDelegate methods has changed some argument type:
- If first argument is `&mut self`, the `cx` has been changed to `&mut
Context<ListState<Self>>` or `&mut Context<TableState<Self>>`.
```diff
- fn confirm(&mut self, _secondary: bool, _: &mut Window, cx: &mut
Context<List<Self>>)
+ fn confirm(&mut self, _secondary: bool, _: &mut Window, cx: &mut
Context<ListState<Self>>)
```
- If first argument is `&self`, the `cx` has been changed to `&mut App`.
```diff
- fn render_item(&self, ix: IndexPath, _: &mut Window, _: &mut
Context<List<Self>>)
+ fn render_item(&self, ix: IndexPath, _: &mut Window, _: &mut App)
```