From 8e555f6b37fbae8fa6c81579b4599fe036e8f16b Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 8 Jul 2026 21:14:13 +1000 Subject: [PATCH] [UI] Add form submission shortcut (#12328) - Ctrl + enter submits the form --- docs/docs/concepts/user_interface.md | 8 ++++++++ src/frontend/lib/functions/Events.tsx | 7 +++++-- src/frontend/src/components/forms/ApiForm.tsx | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/docs/concepts/user_interface.md b/docs/docs/concepts/user_interface.md index 80f9f231c2..a940257046 100644 --- a/docs/docs/concepts/user_interface.md +++ b/docs/docs/concepts/user_interface.md @@ -283,6 +283,14 @@ Example: Editing an existing purchase order via the "Edit Purchase Order" form: {{ image("concepts/ui_form_edit_po.png", "Edit Purchase Order") }} +### Form Submission + +A form can be submitted by clicking the "Submit" button located at the bottom-right corner of the form. + +Alternatively, an open form can be submitted using the keyboard shortcut `Ctrl + Enter` (or `Cmd + Enter` on macOS). This shortcut works even while typing in a form field, providing a quick way to submit the form without needing to reach for the mouse. It is particularly useful in multi-line text fields, where pressing `Enter` inserts a new line rather than submitting the form. + +The keyboard shortcut is only active while a form is open, and follows the same rules as the "Submit" button - for example, it has no effect while the form is loading, or when editing an existing item without any changes. + ### Confirm Actions Many actions within InvenTree require user confirmation before they can be executed. This is typically implemented through the use of confirmation dialogs, which prompt the user to confirm their intention before proceeding with the action. diff --git a/src/frontend/lib/functions/Events.tsx b/src/frontend/lib/functions/Events.tsx index 115e8939a8..9374131965 100644 --- a/src/frontend/lib/functions/Events.tsx +++ b/src/frontend/lib/functions/Events.tsx @@ -17,7 +17,10 @@ export type InvenTreeHotkeyItem = [ HotkeyItemOptions? ]; -export function useInvenTreeHotkeys(_keys: InvenTreeHotkeyItem[]) { +export function useInvenTreeHotkeys( + _keys: InvenTreeHotkeyItem[], + tagsToIgnore?: string[] +) { const keyelems: [string, string][] = _keys.map(([key, description]) => [ key, description @@ -29,7 +32,7 @@ export function useInvenTreeHotkeys(_keys: InvenTreeHotkeyItem[]) { HotkeyItemOptions? ][] = _keys.map(([key, _, handler, options]) => [key, handler, options]); // Register the hotkeys using the Mantine hook - useHotkeys(mappedHotkeys); + useHotkeys(mappedHotkeys, tagsToIgnore); // register to helper state to store hotkeys // This allows us to display the hotkeys in the UI diff --git a/src/frontend/src/components/forms/ApiForm.tsx b/src/frontend/src/components/forms/ApiForm.tsx index 86c5144ad7..1d65b5784f 100644 --- a/src/frontend/src/components/forms/ApiForm.tsx +++ b/src/frontend/src/components/forms/ApiForm.tsx @@ -24,6 +24,7 @@ import { useNavigate } from 'react-router-dom'; import { Boundary } from '@lib/components/Boundary'; import { isTrue } from '@lib/functions/Conversion'; +import { useInvenTreeHotkeys } from '@lib/functions/Events'; import { type NestedDict, constructFormUrl, @@ -599,6 +600,23 @@ export function ApiForm({ [props.onFormError] ); + // Submit the form with Ctrl+Enter (Cmd+Enter on Mac) while it is open. + // An empty tagsToIgnore list allows the hotkey to fire from within form inputs. + useInvenTreeHotkeys( + [ + [ + 'mod+Enter', + t`Submit form`, + () => { + if (!isLoading && (!props.fetchInitialData || isDirty)) { + form.handleSubmit(submitForm, onFormError)(); + } + } + ] + ], + [] + ); + if (optionsLoading || initialDataQuery.isFetching) { return (