Files
oak-gpui/crates/picker/src/head.rs
T
Bennet Bo FennerandAgus Zubiaga acb3406eb8 editor: Wrap placeholder if text overflows (#37919)
This fixes an issue where long placeholders would be cut off, e.g. in a
Claude Code thread:

<img width="387" height="115" alt="image"
src="https://github.com/user-attachments/assets/831a54aa-cf2b-4d87-af86-e368a5936f6b"
/>

Now:

<img width="354" height="115" alt="image"
src="https://github.com/user-attachments/assets/e5df5e05-0869-4db2-8dee-38611263191c"
/>


Most of the changes in this PR are caused by us requiring `&mut Window`
in `set_placeholder_text`.

Release Notes:

- Fixed an issue where placeholders inside editors would not wrap

---------

Co-authored-by: Agus Zubiaga <agus@zed.dev>
2025-09-10 15:38:19 +00:00

69 lines
1.8 KiB
Rust

use std::sync::Arc;
use editor::{Editor, EditorEvent};
use gpui::{App, Entity, FocusHandle, Focusable, prelude::*};
use ui::prelude::*;
/// The head of a [`Picker`](crate::Picker).
pub(crate) enum Head {
/// Picker has an editor that allows the user to filter the list.
Editor(Entity<Editor>),
/// Picker has no head, it's just a list of items.
Empty(Entity<EmptyHead>),
}
impl Head {
pub fn editor<V: 'static>(
placeholder_text: Arc<str>,
edit_handler: impl FnMut(&mut V, &Entity<Editor>, &EditorEvent, &mut Window, &mut Context<V>)
+ 'static,
window: &mut Window,
cx: &mut Context<V>,
) -> Self {
let editor = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text(placeholder_text.as_ref(), window, cx);
editor
});
cx.subscribe_in(&editor, window, edit_handler).detach();
Self::Editor(editor)
}
pub fn empty<V: 'static>(
blur_handler: impl FnMut(&mut V, &mut Window, &mut Context<V>) + 'static,
window: &mut Window,
cx: &mut Context<V>,
) -> Self {
let head = cx.new(EmptyHead::new);
cx.on_blur(&head.focus_handle(cx), window, blur_handler)
.detach();
Self::Empty(head)
}
}
/// An invisible element that can hold focus.
pub(crate) struct EmptyHead {
focus_handle: FocusHandle,
}
impl EmptyHead {
fn new(cx: &mut Context<Self>) -> Self {
Self {
focus_handle: cx.focus_handle(),
}
}
}
impl Render for EmptyHead {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().track_focus(&self.focus_handle(cx))
}
}
impl Focusable for EmptyHead {
fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}