From 73be54a0f70f4c41d0c0dc85bd97d88459c22171 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 11 Apr 2025 19:13:17 +0800 Subject: [PATCH] input: Improve clear button position in Input. (#782) | Before | After | | -- | -- | | image | image | --- crates/story/src/input_story.rs | 22 ++++++++--- crates/ui/locales/ui.yml | 6 +++ crates/ui/src/button/button.rs | 1 + crates/ui/src/input/input.rs | 58 +++++++++++++++++------------ crates/ui/src/input/number_input.rs | 4 +- crates/ui/src/list/list.rs | 3 +- 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/crates/story/src/input_story.rs b/crates/story/src/input_story.rs index 97d8b55f..5aad52a9 100644 --- a/crates/story/src/input_story.rs +++ b/crates/story/src/input_story.rs @@ -11,7 +11,7 @@ use gpui_component::{ checkbox::Checkbox, h_flex, input::{InputEvent, NumberInput, NumberInputEvent, OtpInput, StepAction, TextInput}, - v_flex, FocusableCycle, IconName, Sizable, + v_flex, FocusableCycle, Icon, IconName, Sizable, }; actions!(input_story, [Tab, TabPrev]); @@ -139,21 +139,33 @@ impl InputStory { let prefix_input1 = cx.new(|cx| { TextInput::new(window, cx) - .prefix(|_, _| div().child(IconName::Search).ml_3()) + .prefix(|_, _| div().child(Icon::new(IconName::Search).small()).ml_3()) .placeholder("Search some thing...") .cleanable() }); let suffix_input1 = cx.new(|cx| { TextInput::new(window, cx) - .suffix(|_, _| div().child(IconName::Info).mr_3()) + .suffix(|_, _| { + Button::new("info") + .ghost() + .icon(IconName::Info) + .xsmall() + .mr_3() + }) .placeholder("This input only support [a-zA-Z0-9] characters.") .pattern(regex::Regex::new(r"^[a-zA-Z0-9]*$").unwrap()) .cleanable() }); let both_input1 = cx.new(|cx| { TextInput::new(window, cx) - .prefix(|_, _| div().child(IconName::Search).ml_3()) - .suffix(|_, _| div().child(IconName::Info).mr_3()) + .prefix(|_, _| div().child(Icon::new(IconName::Search).small()).ml_3()) + .suffix(|_, _| { + Button::new("info") + .ghost() + .icon(IconName::Info) + .xsmall() + .mr_3() + }) .cleanable() .placeholder("This input have prefix and suffix.") }); diff --git a/crates/ui/locales/ui.yml b/crates/ui/locales/ui.yml index 0c3f487a..a802c835 100644 --- a/crates/ui/locales/ui.yml +++ b/crates/ui/locales/ui.yml @@ -149,3 +149,9 @@ Modal: zh-CN: 取消 zh-HK: 取消 it: Annulla +List: + search_placeholder: + en: Search... + zh-CN: 搜索... + zh-HK: 搜索... + it: Ricerca... diff --git a/crates/ui/src/button/button.rs b/crates/ui/src/button/button.rs index 4729d8c9..dd43a0c6 100644 --- a/crates/ui/src/button/button.rs +++ b/crates/ui/src/button/button.rs @@ -355,6 +355,7 @@ impl RenderOnce for Button { self.base .id(self.id) + .cursor_default() .flex() .items_center() .justify_center() diff --git a/crates/ui/src/input/input.rs b/crates/ui/src/input/input.rs index 43717c2b..add4acf2 100644 --- a/crates/ui/src/input/input.rs +++ b/crates/ui/src/input/input.rs @@ -33,7 +33,7 @@ use crate::history::History; use crate::indicator::Indicator; use crate::input::clear_button; use crate::scroll::{Scrollbar, ScrollbarAxis, ScrollbarState}; -use crate::StyledExt; +use crate::{h_flex, StyledExt}; use crate::{ActiveTheme, Root}; use crate::{IconName, Size}; use crate::{Sizable, StyleSized}; @@ -1756,6 +1756,13 @@ impl Render for TextInput { let prefix = self.prefix.as_ref().map(|build| build(window, cx)); let suffix = self.suffix.as_ref().map(|build| build(window, cx)); + let show_clear_button = + self.cleanable && !self.loading && !self.text.is_empty() && self.is_single_line(); + let bg = if self.disabled { + cx.theme().muted + } else { + cx.theme().background + }; div() .flex() @@ -1815,40 +1822,45 @@ impl Render for TextInput { .when_some(self.height, |this, height| this.h(height)) }) .when(self.appearance, |this| { - this.bg(if self.disabled { - cx.theme().muted - } else { - cx.theme().background - }) - .border_color(cx.theme().input) - .border_1() - .rounded(cx.theme().radius) - .when(cx.theme().shadow, |this| this.shadow_sm()) - .when(focused, |this| this.focused_border(cx)) + this.bg(bg) + .border_color(cx.theme().input) + .border_1() + .rounded(cx.theme().radius) + .when(cx.theme().shadow, |this| this.shadow_sm()) + .when(focused, |this| this.focused_border(cx)) }) .when(prefix.is_none(), |this| this.input_pl(self.size)) - .when(suffix.is_none(), |this| this.input_pr(self.size)) - .children(prefix) - .gap(gap_x) + .input_pr(self.size) .items_center() + .gap(gap_x) + .children(prefix) .child( div() - .id("TextElement") + .id("text-element") .flex_1() .when(self.is_multi_line(), |this| this.h_full()) .flex_grow() .overflow_x_hidden() .child(TextElement::new(cx.entity().clone())), ) - .when(self.loading, |this| { - this.child(Indicator::new().color(cx.theme().muted_foreground)) - }) - .children(self.render_toggle_mask_button(window, cx)) - .when( - self.cleanable && !self.loading && !self.text.is_empty() && self.is_single_line(), - |this| this.child(clear_button(cx).on_click(cx.listener(Self::clean))), + .child( + h_flex() + .id("suffix") + .absolute() + .gap(gap_x) + .bg(bg) + .items_center() + .when(suffix.is_none(), |this| this.pr_1()) + .right_0() + .when(self.loading, |this| { + this.child(Indicator::new().color(cx.theme().muted_foreground)) + }) + .children(self.render_toggle_mask_button(window, cx)) + .when(show_clear_button, |this| { + this.child(clear_button(cx).on_click(cx.listener(Self::clean))) + }) + .children(suffix), ) - .children(suffix) .when(self.is_multi_line(), |this| { let entity_id = cx.entity().entity_id(); if self.last_layout.is_some() { diff --git a/crates/ui/src/input/number_input.rs b/crates/ui/src/input/number_input.rs index fc8ac79b..b049b232 100644 --- a/crates/ui/src/input/number_input.rs +++ b/crates/ui/src/input/number_input.rs @@ -164,8 +164,8 @@ impl Render for NumberInput { // Sync size to input at first. self.sync_size_to_input_if_needed(window, cx); let btn_size = match self.size { - Size::XSmall | Size::Small => Size::XSmall, - _ => Size::Small, + Size::XSmall | Size::Small => Size::Size(px(16.)), + _ => Size::XSmall, }; h_flex() diff --git a/crates/ui/src/list/list.rs b/crates/ui/src/list/list.rs index 9489b661..fe60106c 100644 --- a/crates/ui/src/list/list.rs +++ b/crates/ui/src/list/list.rs @@ -15,6 +15,7 @@ use gpui::{ Window, }; use gpui::{px, App, Context, EventEmitter, MouseDownEvent, ScrollStrategy, Subscription}; +use rust_i18n::t; use smol::Timer; use super::loading::Loading; @@ -173,7 +174,7 @@ where TextInput::new(window, cx) .appearance(false) .prefix(|_, cx| Icon::new(IconName::Search).text_color(cx.theme().muted_foreground)) - .placeholder("Search...") + .placeholder(t!("List.search_placeholder")) .cleanable() });