From 044ce9ee640206709f2612270502856448858547 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Mon, 17 Apr 2023 13:07:48 +0200 Subject: [PATCH 1/2] Fix context menu position when opened via keyboard --- changelog/unreleased/bugfix-context-menu-keyboard | 6 ++++++ packages/web-pkg/src/helpers/contextMenuDropdown.ts | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 changelog/unreleased/bugfix-context-menu-keyboard diff --git a/changelog/unreleased/bugfix-context-menu-keyboard b/changelog/unreleased/bugfix-context-menu-keyboard new file mode 100644 index 00000000000..1128d8137cf --- /dev/null +++ b/changelog/unreleased/bugfix-context-menu-keyboard @@ -0,0 +1,6 @@ +Bugfix: Opening context menu via keyboard + +The position of the context menu when opened via keyboard has been fixed. + +https://github.com/owncloud/web/pull/8827 +https://github.com/owncloud/web/issues/8232 diff --git a/packages/web-pkg/src/helpers/contextMenuDropdown.ts b/packages/web-pkg/src/helpers/contextMenuDropdown.ts index dbfca64240d..4a5361ee50d 100644 --- a/packages/web-pkg/src/helpers/contextMenuDropdown.ts +++ b/packages/web-pkg/src/helpers/contextMenuDropdown.ts @@ -1,11 +1,16 @@ export const displayPositionedDropdown = (dropdown, event, contextMenuButton) => { const contextMenuButtonPos = contextMenuButton.$el.getBoundingClientRect() + const isKeyboardEvent = event.clientY === 0 + const yValue = isKeyboardEvent + ? event.srcElement?.getBoundingClientRect().top || 0 + : event.clientY + dropdown.setProps({ getReferenceClientRect: () => ({ width: 0, height: 0, - top: event.clientY, - bottom: event.clientY, + top: yValue, + bottom: yValue, /** * If event type is 'contextmenu' the trigger was a right click on the table row, * so we render the dropdown at the position of the mouse pointer. From f50668f50bcde6170b21c6020a5966d692bb1bc9 Mon Sep 17 00:00:00 2001 From: Jannik Stehle Date: Mon, 17 Apr 2023 13:33:47 +0200 Subject: [PATCH 2/2] Add unit tests for the vertical context menu button placement --- .../unit/helpers/contextMenuDropdown.spec.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/web-pkg/tests/unit/helpers/contextMenuDropdown.spec.ts b/packages/web-pkg/tests/unit/helpers/contextMenuDropdown.spec.ts index 2e551b6c825..da11b0b0c15 100644 --- a/packages/web-pkg/tests/unit/helpers/contextMenuDropdown.spec.ts +++ b/packages/web-pkg/tests/unit/helpers/contextMenuDropdown.spec.ts @@ -4,7 +4,7 @@ describe('displayPositionedDropdown', () => { it('shows the dropdown', () => { const dropdown = { setProps: jest.fn(), show: jest.fn() } const ctxMenuBtn = { $el: { getBoundingClientRect: jest.fn() } } - displayPositionedDropdown(dropdown, undefined, ctxMenuBtn) + displayPositionedDropdown(dropdown, {}, ctxMenuBtn) expect(dropdown.show).toHaveBeenCalled() }) it('horizontally positions the drop at the cursor for "contextmenu"-event', () => { @@ -38,4 +38,35 @@ describe('displayPositionedDropdown', () => { expect(data.left).toEqual(ctxMenuBtnX) expect(data.right).toEqual(ctxMenuBtnX) }) + it('vertically positions the drop via "clientY" if given', () => { + const event = { clientY: 100 } + let dropdownProps + const dropdown = { + setProps: jest.fn((props) => { + dropdownProps = props + }), + show: jest.fn() + } + const ctxMenuBtn = { $el: { getBoundingClientRect: jest.fn(() => ({ x: 200 })) } } + displayPositionedDropdown(dropdown, event, ctxMenuBtn) + const { top, bottom } = dropdownProps.getReferenceClientRect() + expect(top).toEqual(event.clientY) + expect(bottom).toEqual(event.clientY) + }) + it('vertically positions the drop via the context button position if "clientY" is 0', () => { + const yPos = 200 + const event = { clientY: 0, srcElement: { getBoundingClientRect: () => ({ top: yPos }) } } + let dropdownProps + const dropdown = { + setProps: jest.fn((props) => { + dropdownProps = props + }), + show: jest.fn() + } + const ctxMenuBtn = { $el: { getBoundingClientRect: jest.fn(() => ({ x: 200 })) } } + displayPositionedDropdown(dropdown, event, ctxMenuBtn) + const { top, bottom } = dropdownProps.getReferenceClientRect() + expect(top).toEqual(yPos) + expect(bottom).toEqual(yPos) + }) })