mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-13 21:53:43 +01:00
Merge pull request #34487 from overleaf/mg-fix-nested-context-menu
Block native context menu on editor context menu and fix focus styling GitOrigin-RevId: c2d59e7acc59019b5e2777cc1bf3ad24a7d8e54e
This commit is contained in:
+38
-36
@@ -49,42 +49,44 @@ const EditorContextMenuContent: FC = memo(function EditorContextMenuContent() {
|
||||
|
||||
return (
|
||||
<Dropdown show onToggle={onToggle}>
|
||||
<DropdownMenu
|
||||
ref={menuRef}
|
||||
show
|
||||
tabIndex={0}
|
||||
className="dropdown-menu-unpositioned"
|
||||
onKeyDown={event => {
|
||||
switch (event.code) {
|
||||
case 'Escape':
|
||||
case 'Tab':
|
||||
event.preventDefault()
|
||||
closeMenu()
|
||||
break
|
||||
}
|
||||
}}
|
||||
>
|
||||
{menuItems.map((menuItem, index) => (
|
||||
<Fragment key={index}>
|
||||
{menuItem.separatorAbove && <DropdownDivider />}
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
onClick={() => menuItem.handler()}
|
||||
disabled={menuItem.disabled}
|
||||
trailingIcon={
|
||||
menuItem.shortcut ? (
|
||||
<span>{menuItem.shortcut}</span>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{menuItem.label}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
</Fragment>
|
||||
))}
|
||||
<EditorContextMenuFeedback />
|
||||
</DropdownMenu>
|
||||
<div onContextMenu={event => event.preventDefault()}>
|
||||
<DropdownMenu
|
||||
ref={menuRef}
|
||||
show
|
||||
tabIndex={0}
|
||||
className="dropdown-menu-unpositioned"
|
||||
onKeyDown={event => {
|
||||
switch (event.code) {
|
||||
case 'Escape':
|
||||
case 'Tab':
|
||||
event.preventDefault()
|
||||
closeMenu()
|
||||
break
|
||||
}
|
||||
}}
|
||||
>
|
||||
{menuItems.map((menuItem, index) => (
|
||||
<Fragment key={index}>
|
||||
{menuItem.separatorAbove && <DropdownDivider />}
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
onClick={() => menuItem.handler()}
|
||||
disabled={menuItem.disabled}
|
||||
trailingIcon={
|
||||
menuItem.shortcut ? (
|
||||
<span>{menuItem.shortcut}</span>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{menuItem.label}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
</Fragment>
|
||||
))}
|
||||
<EditorContextMenuFeedback />
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</Dropdown>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -133,6 +133,10 @@ $dropdown-item-min-height: 36px;
|
||||
|
||||
&:focus {
|
||||
background: none;
|
||||
|
||||
// Bootstrap sets the hover text colour on plain :focus too; reset it so a
|
||||
// mouse-focused (not :focus-visible), non-hovered item stays readable.
|
||||
color: var(--dropdown-text-color);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
|
||||
+36
@@ -1288,4 +1288,40 @@ describe('editor context menu', { scrollBehavior: false }, function () {
|
||||
cy.findByRole('menu').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when right-clicking inside the open menu', function () {
|
||||
it('should suppress the native menu and stay open', function () {
|
||||
const scope = mockScope()
|
||||
|
||||
cy.mount(
|
||||
<TestContainer>
|
||||
<EditorProviders scope={scope}>
|
||||
<CodeMirrorEditor />
|
||||
</EditorProviders>
|
||||
</TestContainer>
|
||||
)
|
||||
|
||||
cy.get('.cm-line').eq(10).rightclick()
|
||||
cy.findByRole('menu').should('be.visible')
|
||||
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findAllByRole('menuitem')
|
||||
.first()
|
||||
.then($item => {
|
||||
const event = new MouseEvent('contextmenu', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
// dispatchEvent returns false when preventDefault was called
|
||||
const notPrevented = $item[0].dispatchEvent(event)
|
||||
expect(notPrevented, 'native context menu prevented').to.equal(
|
||||
false
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
// The second contextmenu event keeps the custom menu open
|
||||
cy.findByRole('menu').should('be.visible')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user