gpui-component/crates/story/src/textarea_story.rs
Jason Lee b97abd6394
input: Fix auto-grow height. (#865)
Fix #864 

Updated InputState API to split `single_line`, `multi_line` and
`auto_grow`.

The `InputState::new` for default single_line, and added `multi_line`
and `auto_grow` to change other mode.

### With no wrap

https://github.com/user-attachments/assets/22a8f0d6-e264-4f39-bb30-386a41975d2b

### With soft wrap

https://github.com/user-attachments/assets/b71f0fb1-5937-470b-a278-8b1de7cfd7d7
2025-05-19 19:26:27 +08:00

179 lines
5.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use gpui::{
actions, px, App, AppContext as _, ClickEvent, Context, Entity, FocusHandle, Focusable,
InteractiveElement, IntoElement, KeyBinding, ParentElement as _, Render, Styled, Window,
};
use crate::section;
use gpui_component::{
button::Button,
h_flex,
input::{InputState, TextInput},
v_flex, FocusableCycle, Sizable,
};
actions!(input_story, [Tab, TabPrev]);
const CONTEXT: &str = "TextareaStory";
pub fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("shift-tab", TabPrev, Some(CONTEXT)),
KeyBinding::new("tab", Tab, Some(CONTEXT)),
])
}
pub struct TextareaStory {
textarea: Entity<InputState>,
textarea_auto_grow: Entity<InputState>,
}
impl super::Story for TextareaStory {
fn title() -> &'static str {
"Textarea"
}
fn description() -> &'static str {
"TextInput with multi-line mode."
}
fn closable() -> bool {
false
}
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
Self::view(window, cx)
}
}
impl TextareaStory {
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self::new(window, cx))
}
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let textarea = cx.new(|cx| {
InputState::new(window, cx)
.multi_line()
.rows(10)
.placeholder("Enter text here...").default_value(
unindent::unindent(
r#"Hello 世界this is GPUI component.
The GPUI Component is a collection of UI components for GPUI framework, including.
Button, Input, Checkbox, Radio, Dropdown, Tab, and more...
Here is an application that is built by using GPUI Component.
> This application is still under development, not published yet.
![image](https://github.com/user-attachments/assets/559a648d-19df-4b5a-b563-b78cc79c8894)
![image](https://github.com/user-attachments/assets/5e06ad5d-7ea0-43db-8d13-86a240da4c8d)
## Demo
If you want to see the demo, here is a some demo applications.
"#,
)
)
});
let textarea_auto_grow = cx.new(|cx| {
InputState::new(window, cx)
.auto_grow(1, 5)
.placeholder("Enter text here...")
.default_value("Hello 世界this is GPUI component.")
});
Self {
textarea,
textarea_auto_grow,
}
}
fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
self.cycle_focus(true, window, cx);
}
fn tab_prev(&mut self, _: &TabPrev, window: &mut Window, cx: &mut Context<Self>) {
self.cycle_focus(false, window, cx);
}
fn on_insert_text_to_textarea(
&mut self,
_: &ClickEvent,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.textarea.update(cx, |input, cx| {
input.insert("Hello 你好", window, cx);
});
}
fn on_replace_text_to_textarea(
&mut self,
_: &ClickEvent,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.textarea.update(cx, |input, cx| {
input.replace("Hello 你好", window, cx);
});
}
}
impl FocusableCycle for TextareaStory {
fn cycle_focus_handles(&self, _: &mut Window, _: &mut App) -> Vec<FocusHandle> {
[].to_vec()
}
}
impl Focusable for TextareaStory {
fn focus_handle(&self, cx: &gpui::App) -> gpui::FocusHandle {
self.textarea.focus_handle(cx)
}
}
impl Render for TextareaStory {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.key_context(CONTEXT)
.id("textarea-story")
.on_action(cx.listener(Self::tab))
.on_action(cx.listener(Self::tab_prev))
.size_full()
.justify_start()
.gap_3()
.child(
section("Textarea").child(
v_flex()
.gap_2()
.w_full()
.child(TextInput::new(&self.textarea).h(px(320.)))
.child(
h_flex()
.gap_2()
.child(
Button::new("btn-insert-text")
.xsmall()
.label("Insert Text")
.on_click(cx.listener(Self::on_insert_text_to_textarea)),
)
.child(
Button::new("btn-replace-text")
.xsmall()
.label("Replace Text")
.on_click(cx.listener(Self::on_replace_text_to_textarea)),
),
),
),
)
.child(
section("Textarea Auto Grow").child(
v_flex()
.w_full()
.child(TextInput::new(&self.textarea_auto_grow)),
),
)
}
}