diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 073c032e04..5c94606009 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -48,6 +48,7 @@ Changelog * Fix: Fix timezone handling in the `timesince_last_update` template tag (Matt Westcott) * Fix: Fix Postgres phrase search to respect the language set in settings (Ihar Marhitych) * Fix: Retain query parameters when switching between locales in the page chooser (Abdelrahman Hamada, Sage Abdullah) + * Fix: Add `w-kbd-scope-value` with support for `global` so that specific keyboard shortcuts (e.g. ctrl+s/cmd+s) trigger consistently even when focused on fields (Neeraj Yetheendran) * Docs: Add contributing development documentation on how to work with a fork of Wagtail (Nix Asteri, Dan Braghis) * Docs: Make sure the settings panel is listed in tabbed interface examples (Tibor Leupold) * Docs: Update content and page names to their US spelling instead of UK spelling (Victoria Poromon) diff --git a/client/src/controllers/KeyboardController.test.js b/client/src/controllers/KeyboardController.test.js index acf8d65d1a..93743c3a77 100644 --- a/client/src/controllers/KeyboardController.test.js +++ b/client/src/controllers/KeyboardController.test.js @@ -126,4 +126,34 @@ describe('KeyboardController', () => { expect(buttonClickMock).toHaveBeenCalledTimes(1); }); }); + + describe('keyboard shortcut with scope value', () => { + it('should fail when the scope value is not global', async () => { + expect(buttonClickMock).not.toHaveBeenCalled(); + + await setup(` + + + `); + + // Simulate keydown while target is text input + simulateKey({ key: 'j' }, document.getElementById('input')); + + expect(buttonClickMock).not.toHaveBeenCalled(); + }); + + it('should set the scope value to global when specified', async () => { + expect(buttonClickMock).not.toHaveBeenCalled(); + + await setup(` + + + `); + + // Simulate keydown while target is text input + simulateKey({ key: 'j' }, document.getElementById('input')); + + expect(buttonClickMock).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/client/src/controllers/KeyboardController.ts b/client/src/controllers/KeyboardController.ts index f8c1b8c0ec..660244d78a 100644 --- a/client/src/controllers/KeyboardController.ts +++ b/client/src/controllers/KeyboardController.ts @@ -1,6 +1,9 @@ import { Controller } from '@hotwired/stimulus'; import Mousetrap from 'mousetrap'; +// import with side-effect to add global-bind plugin (see https://github.com/ccampbell/mousetrap/tree/master/plugins/global-bind) +import 'mousetrap/plugins/global-bind/mousetrap-global-bind'; + /** * Adds the ability to trigger a button click event using a * keyboard shortcut declared on the controlled element. @@ -21,10 +24,15 @@ import Mousetrap from 'mousetrap'; export class KeyboardController extends Controller< HTMLButtonElement | HTMLAnchorElement > { - static values = { key: { default: '', type: String } }; + static values = { + key: { default: '', type: String }, + scope: { default: '', type: String }, + }; /** Keyboard shortcut string. */ declare keyValue: string; + /** Scope of the keyboard shortcut, defaults to the normal MouseTrap (non-input) scope. */ + declare scopeValue: '' | 'global'; initialize() { this.handleKey = this.handleKey.bind(this); @@ -50,6 +58,10 @@ export class KeyboardController extends Controller< Mousetrap.unbind(previousKey); } - Mousetrap.bind(key, this.handleKey); + if (this.scopeValue === 'global') { + Mousetrap.bindGlobal(key, this.handleKey); + } else { + Mousetrap.bind(key, this.handleKey); + } } } diff --git a/docs/releases/6.1.md b/docs/releases/6.1.md index 741e3365cf..05f06531b8 100644 --- a/docs/releases/6.1.md +++ b/docs/releases/6.1.md @@ -63,6 +63,7 @@ depth: 1 * Fix timezone handling in the `timesince_last_update` template tag (Matt Westcott) * Fix Postgres phrase search to respect the language set in settings (Ihar Marhitych) * Retain query parameters when switching between locales in the page chooser (Abdelrahman Hamada, Sage Abdullah) + * Add `w-kbd-scope-value` with support for `global` so that specific keyboard shortcuts (e.g. ctrl+s/cmd+s) trigger consistently even when focused on fields (Neeraj Yetheendran) ### Documentation diff --git a/wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html b/wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html index 71971053a1..b3708b2621 100644 --- a/wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +++ b/wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html @@ -5,6 +5,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Saving…' %}" > {% icon name="draft" classname="button-longrunning__icon" %} diff --git a/wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html b/wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html index 52ed732c9e..ad0f7f860f 100644 --- a/wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html +++ b/wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html @@ -24,6 +24,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Saving…' %}" > {% trans 'Save schedule' %} diff --git a/wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html b/wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html index 061ef9e453..842ff8f59b 100644 --- a/wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +++ b/wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html @@ -6,7 +6,7 @@ aria-expanded="false" data-controller="w-tooltip{% if toggle.keyboard_shortcut %} w-kbd{% endif %}" data-side-panel-toggle="{{ panel.name }}" - {% if toggle.keyboard_shortcut %}data-w-kbd-key-value="{{ toggle.keyboard_shortcut }}"{% endif %} + {% if toggle.keyboard_shortcut %}data-w-kbd-key-value="{{ toggle.keyboard_shortcut }}" data-w-kbd-scope-value="global"{% endif %} data-w-tooltip-content-value="{{ panel.title }}" data-w-tooltip-offset-value="[0, 0]" > diff --git a/wagtail/admin/templates/wagtailadmin/workflows/create.html b/wagtail/admin/templates/wagtailadmin/workflows/create.html index 1aa2a0680a..b7286d8e22 100644 --- a/wagtail/admin/templates/wagtailadmin/workflows/create.html +++ b/wagtail/admin/templates/wagtailadmin/workflows/create.html @@ -29,6 +29,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Creating…' %}" > {% icon name="spinner" %} diff --git a/wagtail/admin/templates/wagtailadmin/workflows/create_task.html b/wagtail/admin/templates/wagtailadmin/workflows/create_task.html index 75c854086c..457817d4c6 100644 --- a/wagtail/admin/templates/wagtailadmin/workflows/create_task.html +++ b/wagtail/admin/templates/wagtailadmin/workflows/create_task.html @@ -25,6 +25,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Creating…' %}" > {% icon name="spinner" %} diff --git a/wagtail/admin/templates/wagtailadmin/workflows/edit.html b/wagtail/admin/templates/wagtailadmin/workflows/edit.html index ffff682646..076c2adda9 100644 --- a/wagtail/admin/templates/wagtailadmin/workflows/edit.html +++ b/wagtail/admin/templates/wagtailadmin/workflows/edit.html @@ -53,6 +53,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Saving…' %}" > {% icon name="spinner" %} diff --git a/wagtail/admin/templates/wagtailadmin/workflows/edit_task.html b/wagtail/admin/templates/wagtailadmin/workflows/edit_task.html index ee5e3dcebd..30537a34d0 100644 --- a/wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +++ b/wagtail/admin/templates/wagtailadmin/workflows/edit_task.html @@ -37,6 +37,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Saving…' %}" > {% icon name="spinner" %} diff --git a/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html b/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html index 514a021e2d..0d60d2128e 100644 --- a/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +++ b/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html @@ -7,6 +7,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Publishing…' %}" > {% icon name=icon_name classname="button-longrunning__icon" %} diff --git a/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html b/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html index 979fa660c6..4473fe256a 100644 --- a/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +++ b/wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html @@ -5,6 +5,7 @@ data-controller="w-progress w-kbd" data-action="w-progress#activate" data-w-kbd-key-value="mod+s" + data-w-kbd-scope-value="global" data-w-progress-active-value="{% trans 'Saving…' %}" > {% if draftstate_enabled %}