You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/07/11 17:39:36 UTC

(superset) branch master updated: fix(dashboard): restore arrow key navigation in modal inputs opened from dropdown (#37978)

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 7a752d1c228 fix(dashboard): restore arrow key navigation in modal inputs opened from dropdown (#37978)
7a752d1c228 is described below

commit 7a752d1c228b94b7c12166a1b5b3414a2981e5b2
Author: Ujjwal Jain <ja...@gmail.com>
AuthorDate: Sat Jul 11 23:09:28 2026 +0530

    fix(dashboard): restore arrow key navigation in modal inputs opened from dropdown (#37978)
---
 .../components/ModalTrigger/ModalTrigger.test.tsx  | 42 +++++++++++++++++++++-
 .../src/components/ModalTrigger/index.tsx          | 20 ++++++++++-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/ModalTrigger.test.tsx b/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/ModalTrigger.test.tsx
index aa61ef85c4d..62f42c92c5f 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/ModalTrigger.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/ModalTrigger.test.tsx
@@ -16,7 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { render, screen, userEvent } from '@superset-ui/core/spec';
+import { render, screen, userEvent, fireEvent } from '@superset-ui/core/spec';
+
 import { ModalTrigger } from '.';
 
 const mockedProps = {
@@ -74,3 +75,42 @@ test('should render a modal after click', async () => {
   await userEvent.click(screen.getByRole('button'));
   expect(screen.getByRole('dialog')).toBeInTheDocument();
 });
+
+test('stops propagation of navigation keys to parent elements', async () => {
+  const handleParentKeyDown = jest.fn();
+
+  render(
+    <div onKeyDown={handleParentKeyDown}>
+      <ModalTrigger
+        triggerNode={<span>Trigger</span>}
+        modalBody={<input data-test="modal-input" />}
+      />
+    </div>,
+  );
+
+  await userEvent.click(screen.getByText('Trigger'));
+  const input = await screen.findByTestId('modal-input');
+
+  const blockedKeys = [
+    'ArrowLeft',
+    'ArrowRight',
+    'ArrowUp',
+    'ArrowDown',
+    'Home',
+    'End',
+  ];
+
+  for (const key of blockedKeys) {
+    handleParentKeyDown.mockClear();
+    fireEvent.keyDown(input, { key });
+    expect(handleParentKeyDown).not.toHaveBeenCalled();
+  }
+
+  const allowedKeys = ['Escape', 'Tab'];
+
+  for (const key of allowedKeys) {
+    handleParentKeyDown.mockClear();
+    fireEvent.keyDown(input, { key });
+    expect(handleParentKeyDown).toHaveBeenCalled();
+  }
+});
diff --git a/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/index.tsx
index f344293d096..4f477437027 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/index.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/index.tsx
@@ -27,6 +27,15 @@ import {
 import { Button } from '../Button';
 import { Modal } from '../Modal';
 
+const MENU_NAVIGATION_KEYS = new Set([
+  'ArrowLeft',
+  'ArrowRight',
+  'ArrowUp',
+  'ArrowDown',
+  'Home',
+  'End',
+]);
+
 export interface ModalTriggerProps {
   dialogClassName?: string;
   triggerNode: ReactNode;
@@ -140,7 +149,16 @@ export const ModalTrigger = forwardRef(
           draggableConfig={draggableConfig}
           destroyOnHidden={destroyOnHidden}
         >
-          {modalBody}
+          <div
+            style={{ display: 'contents' }}
+            onKeyDown={e => {
+              if (MENU_NAVIGATION_KEYS.has(e.key)) {
+                e.stopPropagation();
+              }
+            }}
+          >
+            {modalBody}
+          </div>
         </Modal>
       </>
     );