Skip to content

Commit 1bb2779

Browse files
renathorenathokevin940726aaronrobertshawgetdave
authored
Fix the navigation issue inside cover blocks (#66093)
Co-authored-by: renatho <renathoc@git.wordpress.org> Co-authored-by: kevin940726 <kevin940726@git.wordpress.org> Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org> Co-authored-by: getdave <get_dave@git.wordpress.org> Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
1 parent 0decb96 commit 1bb2779

3 files changed

Lines changed: 107 additions & 3 deletions

File tree

‎packages/block-library/src/cover/style.scss‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@
100100
color: inherit;
101101
// Reset the fixed LTR direction at the root of the block in RTL languages.
102102
/*rtl:raw: direction: rtl; */
103+
104+
// Reset the z-index to auto when the body has a modal open. So when the
105+
// modal is inside the cover, it doesn't create a stacking context.
106+
@at-root .has-modal-open & {
107+
z-index: auto;
108+
}
103109
}
104110

105111
// Position: Top

‎packages/block-library/src/navigation/edit/index.js‎

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,33 @@ import AccessibleDescription from './accessible-description';
7373
import AccessibleMenuDescription from './accessible-menu-description';
7474
import { unlock } from '../../lock-unlock';
7575

76+
function useResponsiveMenu( navRef ) {
77+
const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] =
78+
useState( false );
79+
80+
useEffect( () => {
81+
if ( ! navRef.current ) {
82+
return;
83+
}
84+
85+
const htmlElement = navRef.current.ownerDocument.documentElement;
86+
87+
// Add a `has-modal-open` class to the <html> when the responsive
88+
// menu is open. This reproduces the same behavior of the frontend.
89+
if ( isResponsiveMenuOpen ) {
90+
htmlElement.classList.add( 'has-modal-open' );
91+
} else {
92+
htmlElement.classList.remove( 'has-modal-open' );
93+
}
94+
95+
return () => {
96+
htmlElement?.classList.remove( 'has-modal-open' );
97+
};
98+
}, [ navRef, isResponsiveMenuOpen ] );
99+
100+
return [ isResponsiveMenuOpen, setResponsiveMenuVisibility ];
101+
}
102+
76103
function ColorTools( {
77104
textColor,
78105
setTextColor,
@@ -284,8 +311,10 @@ function Navigation( {
284311
__unstableMarkNextChangeAsNotPersistent,
285312
} = useDispatch( blockEditorStore );
286313

314+
const navRef = useRef();
315+
287316
const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] =
288-
useState( false );
317+
useResponsiveMenu( navRef );
289318

290319
const [ overlayMenuPreview, setOverlayMenuPreview ] = useState( false );
291320

@@ -367,8 +396,6 @@ function Navigation( {
367396
__unstableMarkNextChangeAsNotPersistent,
368397
] );
369398

370-
const navRef = useRef();
371-
372399
// The standard HTML5 tag for the block wrapper.
373400
const TagName = 'nav';
374401

‎test/e2e/specs/editor/blocks/cover.spec.js‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,77 @@ test.describe( 'Cover', () => {
226226
await expect( overlay ).toHaveCSS( 'background-color', 'rgb(0, 0, 0)' );
227227
await expect( overlay ).toHaveCSS( 'opacity', '0.5' );
228228
} );
229+
230+
test( 'other cover blocks are not over the navigation block when the menu is open', async ( {
231+
editor,
232+
page,
233+
} ) => {
234+
// Insert a Cover block
235+
await editor.insertBlock( { name: 'core/cover' } );
236+
const coverBlock = editor.canvas.getByRole( 'document', {
237+
name: 'Block: Cover',
238+
} );
239+
240+
// Choose a color swatch to transform the placeholder block into
241+
// a functioning block.
242+
await coverBlock
243+
.getByRole( 'option', {
244+
name: 'Color: Black',
245+
} )
246+
.click();
247+
248+
// Insert a Navigation block inside the Cover block
249+
await editor.selectBlocks( coverBlock );
250+
await coverBlock.getByRole( 'button', { name: 'Add block' } ).click();
251+
await page.keyboard.type( 'Navigation' );
252+
const blockResults = page.getByRole( 'listbox', {
253+
name: 'Blocks',
254+
} );
255+
const blockResultOptions = blockResults.getByRole( 'option' );
256+
await blockResultOptions.nth( 0 ).click();
257+
258+
// Insert a second Cover block.
259+
await editor.insertBlock( { name: 'core/cover' } );
260+
const secondCoverBlock = editor.canvas
261+
.getByRole( 'document', {
262+
name: 'Block: Cover',
263+
} )
264+
.last();
265+
266+
// Choose a color swatch to transform the placeholder block into
267+
// a functioning block.
268+
await secondCoverBlock
269+
.getByRole( 'option', {
270+
name: 'Color: Black',
271+
} )
272+
.click();
273+
274+
// Set the viewport to a small screen and open menu.
275+
await page.setViewportSize( { width: 375, height: 1000 } );
276+
const navigationBlock = editor.canvas.getByRole( 'document', {
277+
name: 'Block: Navigation',
278+
} );
279+
await editor.selectBlocks( navigationBlock );
280+
await editor.canvas
281+
.getByRole( 'button', { name: 'Open menu' } )
282+
.click();
283+
284+
// Check if inner container of the second cover is clickable.
285+
const secondInnerContainer = secondCoverBlock.locator(
286+
'.wp-block-cover__inner-container'
287+
);
288+
let isClickable;
289+
try {
290+
isClickable = await secondInnerContainer.click( {
291+
trial: true,
292+
timeout: 1000, // This test will always take 1 second to run.
293+
} );
294+
} catch ( error ) {
295+
isClickable = false;
296+
}
297+
298+
expect( isClickable ).toBe( false );
299+
} );
229300
} );
230301

231302
class CoverBlockUtils {

0 commit comments

Comments
 (0)