Forms: Cmd-Enter submits from any control in a form
Form sets the ElyForm key context and binds secondary-enter to Submit under it, so a focused tile, chip or button submits too. The prompt enhancer's wash trims anything but letters and digits from its runs, its spacing sits on its parts so nothing gaps at rest, and its tests check that the field takes focus back.
This commit is contained in:
1 parent
66345b7e24
commit
97637dd5dd
6 files changed
+51
-12
No files matched your search
@@ -15,7 +15,10 @@ use crate::{
|
||||
typography::{Caption, Heading, Label},
|
||||
};
|
||||
|
||||
/// Sections stacked with room between them. Cmd-Enter in any field submits the form.
|
||||
/// The key context a form sets, so Cmd-Enter reaches it from any control inside.
|
||||
pub(crate) const FORM_CONTEXT: &str = "ElyForm";
|
||||
|
||||
/// Sections stacked with room between them. Cmd-Enter on any field or control inside submits the form.
|
||||
#[derive(IntoElement)]
|
||||
pub struct Form {
|
||||
id: ElementId,
|
||||
@@ -49,6 +52,7 @@ impl RenderOnce for Form {
|
||||
let id = self.id.clone();
|
||||
div()
|
||||
.id(self.id)
|
||||
.key_context(FORM_CONTEXT)
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_8()
|
||||
|
||||
@@ -4,7 +4,10 @@ use gpui::{
|
||||
};
|
||||
|
||||
use super::setup;
|
||||
use crate::forms::{FieldArray, Form, FormField, Input, InputEvent, TextInput};
|
||||
use crate::{
|
||||
buttons::Button,
|
||||
forms::{FieldArray, Form, FormField, Input, InputEvent, TextInput},
|
||||
};
|
||||
|
||||
struct Signup {
|
||||
name: Entity<TextInput>,
|
||||
@@ -27,13 +30,13 @@ impl Render for Signup {
|
||||
.required()
|
||||
.child(Input::new(&self.name)),
|
||||
)
|
||||
.child(Button::new("signup-save", "Save"))
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn cmd_enter_in_a_field_submits_the_form_once(cx: &mut TestAppContext) {
|
||||
fn signup(cx: &mut TestAppContext) -> (Entity<Signup>, &mut VisualTestContext) {
|
||||
setup(cx);
|
||||
let (view, cx) = cx.add_window_view(|window, cx| {
|
||||
cx.add_window_view(|window, cx| {
|
||||
let name = cx.new(|cx| TextInput::new(window, cx));
|
||||
cx.subscribe(&name, |view: &mut Signup, _, event, _| {
|
||||
if *event == InputEvent::Submit {
|
||||
@@ -46,7 +49,12 @@ fn cmd_enter_in_a_field_submits_the_form_once(cx: &mut TestAppContext) {
|
||||
sent: 0,
|
||||
field_submits: 0,
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn cmd_enter_in_a_field_submits_the_form_once(cx: &mut TestAppContext) {
|
||||
let (view, cx) = signup(cx);
|
||||
cx.update(|window, _| window.focus_next());
|
||||
cx.simulate_input("Ada");
|
||||
cx.simulate_keystrokes("cmd-enter");
|
||||
@@ -54,6 +62,21 @@ fn cmd_enter_in_a_field_submits_the_form_once(cx: &mut TestAppContext) {
|
||||
assert_eq!(counts, (1, 0));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn cmd_enter_on_any_control_in_a_form_submits_it(cx: &mut TestAppContext) {
|
||||
let (view, cx) = signup(cx);
|
||||
cx.update(|window, _| {
|
||||
window.focus_next();
|
||||
window.focus_next();
|
||||
});
|
||||
cx.simulate_keystrokes("cmd-enter");
|
||||
assert_eq!(
|
||||
view.read_with(cx, |view, _| view.sent),
|
||||
1,
|
||||
"the button holds focus"
|
||||
);
|
||||
}
|
||||
|
||||
struct Rows {
|
||||
rows: Vec<&'static str>,
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use super::{
|
||||
edit::{self, next_grapheme, prev_grapheme},
|
||||
element::TextElement,
|
||||
};
|
||||
use crate::forms::structure::FORM_CONTEXT;
|
||||
|
||||
actions!(
|
||||
ely_input,
|
||||
@@ -87,6 +88,7 @@ pub(crate) fn bind_keys(cx: &mut App) {
|
||||
KeyBinding::new("enter", Enter, Some(CONTEXT)),
|
||||
KeyBinding::new("shift-enter", Newline, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-enter", Submit, Some(CONTEXT)),
|
||||
KeyBinding::new("secondary-enter", Submit, Some(FORM_CONTEXT)),
|
||||
];
|
||||
if cfg!(target_os = "macos") {
|
||||
bindings.extend([
|
||||
|
||||
Reference in new issue
Block a user