Make WordPress Core

Opened 5 weeks ago

Last modified 5 weeks ago

#64835 new defect (bug)

Parent menu item is still rendered as dropdown when all submenu items are hidden

Reported by: benniledl's profile benniledl Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Editor Keywords:
Focuses: Cc:

Description

If a menu item has child items, and all of those child items are hidden (by right-clicking and hiding them in the list view on the left side of the editor), the parent item is still displayed as if it had a submenu.

As a result, the parent item still shows the submenu indicator arrow and is treated like a dropdown trigger, even though there are no submenu items left.

Change History (4)

#1 @niravsherasiya7707
5 weeks ago

@benniledl Could you please share more context about the issue and reproduction steps for the issue?

#2 @khushipatel15
5 weeks ago

Can You check and add this code snippet.

// File: wp-includes/blocks/navigation-link.php

function render_block_core_navigation_link( $attributes, $content, $block ) {
    $parent_block = $block; // The current navigation-link block being rendered.

    // ... (existing attribute extraction and HTML markup generation for the <a> tag) ...

    // --- START PROPOSED FIX ---
    // Determine if this navigation link block has *any visible* inner navigation link blocks.
    // The navigation block structure is typically:
    // core/navigation-link (parent)
    //   -> core/submenus
    //      -> [core/navigation-link, core/navigation-link, ...] (children)
    $has_visible_submenu_items = false;
    if ( ! empty( $parent_block->inner_blocks ) ) {
        // Assume the first inner block is core/submenus.
        // This is a safe assumption for a valid navigation-link with children.
        $submenu_block = $parent_block->inner_blocks[0];

        if ( 'core/submenus' === $submenu_block->name && ! empty( $submenu_block->inner_blocks ) ) {
            foreach ( $submenu_block->inner_blocks as $child_link_block ) {
                if ( 'core/navigation-link' === $child_link_block->name ) {
                    // Check the 'metadata.visibility' attribute of the child link block.
                    // Default to 'visible' if the attribute is not explicitly set.
                    $child_metadata   = isset( $child_link_block->parsed_block['attrs']['metadata'] ) ? $child_link_block->parsed_block['attrs']['metadata'] : array();
                    $child_visibility = isset( $child_metadata['visibility'] ) ? $child_metadata['visibility'] : 'visible';

                    if ( 'hidden' !== $child_visibility ) {
                        $has_visible_submenu_items = true;
                        break; // Found at least one visible child, so this parent has a visible submenu.
                    }
                }
            }
        }
    }

    // Replace the existing `$has_submenu = ! empty( $parent_block->inner_blocks );`
    // with the new logic based on visible children.
    $has_submenu = $has_visible_submenu_items;
    // --- END PROPOSED FIX ---

    // Add classes to the <li> element based on $has_submenu.
    $li_classes = array();
    if ( $has_submenu ) {
        $li_classes[] = 'has-link-submenu'; // This class often triggers dropdown styling.
        // Add other classes like 'wp-block-navigation-item--has-submenu' as needed.
    }
    // ... (further class processing for current item, etc.) ...

    // Build the content of the <li> element.
    $list_item_content = $block_markup . $attributes['label'] . '</a>'; // The <a> tag and label.

    if ( $has_submenu ) {
        // Add the submenu indicator arrow button.
        $list_item_content .= '<button aria-label="' . esc_attr__( 'Open submenu', 'default' ) . '" class="wp-block-navigation__submenu-icon wp-block-navigation-item__content-icon" data-wp-action="core#toggle" data-wp-on--click="actions.toggleMenuOnHover" data-wp-on--keydown="actions.toggleMenuOnHover" data-wp-bind--aria-expanded="state.isMenuOpen"></button>';
    }

    // Render inner blocks (the actual submenu). These will automatically filter based on their own visibility.
    $inner_blocks_content = '';
    foreach ( $parent_block->inner_blocks as $inner_block ) {
        // The core/submenus block itself also needs to ensure it only renders visible children,
        // but its render callback usually handles this.
        $inner_blocks_content .= $inner_block->render();
    }

    // Assemble the final list item HTML.
    return '<li class="' . esc_attr( implode( ' ', $li_classes ) ) . '">' . $list_item_content . $inner_blocks_content . '</li>';
}
Last edited 5 weeks ago by dd32 (previous) (diff)

This ticket was mentioned in Slack in #meta by benniledl. View the logs.


5 weeks ago

This ticket was mentioned in Slack in #forums by benniledl. View the logs.


5 weeks ago

Note: See TracTickets for help on using tickets.