Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

current-menu-item does not get applied to custom links in navigation block #61266

Open
ethanclevenger91 opened this issue May 1, 2024 · 10 comments
Labels
[Block] Navigation Affects the Navigation Block Needs Testing Needs further testing to be confirmed. [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. [Type] Bug An existing feature does not function as intended

Comments

@ethanclevenger91
Copy link

ethanclevenger91 commented May 1, 2024

Description

I expect custom links within the navigation block to get the current-menu-item class when on that link on the site, as was the case for classic nav menus. Currently, they do not receive this class.

Step-by-step reproduction instructions

  1. New WP site (at, say, example.test)
  2. Install TT4
  3. Create new navigation menu via Editor
  4. Add "Custom Link" to navigation using the WordPress install's URL and some slug, such as "http://example.test/link"
  5. Create a new page titled "Link" (or otherwise) so that its permalink matches the menu item you created, such as "http://example.test/link"
  6. Inspect nav menu on website front end
  7. See no current-menu-item class

For quick reproduction, these steps are a bit absurd. The issue is more reasonably encountered when, for instance, you have a custom taxonomy. The prepared nav blocks (like Category Link or Tag Link or Page Link) do not include custom taxonomy term archive links, so you must use a Custom Link item, and the correct classes are not applied in that scenario, either.

Screenshots, screen recording, code snippet

No response

Environment info

WP 6.5.2, Gutenberg 18.2.0. Also present w/o Gutenberg

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@ethanclevenger91 ethanclevenger91 added the [Type] Bug An existing feature does not function as intended label May 1, 2024
@jordesign jordesign added [Block] Navigation Affects the Navigation Block Needs Testing Needs further testing to be confirmed. labels May 5, 2024
@jhimross
Copy link

jhimross commented May 10, 2024

I replicated the issue and can reproduce it by following the instructions above. I tested this using a fresh WP installation with WP version 6.5.2 and using Twenty Twenty Four theme. Watch this when adding menu using "custom link":- https://share.zight.com/E0ueEXKD

And this what will happen, when I added a menu item not using the "custom link" feature, it shows this aria-current="page". See this: https://share.zight.com/JruE7pEn

@chuckpearson
Copy link

I can replicate this issue and have the same problem. When I add a menu item to the navigation in Site Editor, if the item is a custom post type, the menu item does not get the current-menu-item class applied and does not get the aria-current either.

@jeroensmeets
Copy link

For anyone facing this issue, I have added this filter to functions.php as a fix. Replace str_ends_with if you're on PHP < 8.

// add current-menu-item class to custom links in navigation block
function filter_custom_link_block( $html ) {
    // this works for page links
    if ( false !== strpos( $html, 'current-menu-item' ) ) {
        return $html;
    }

    preg_match_all( '/href=["\']?([^"\'>]+)["\']?/', $html, $matches );

    if ( count( $matches ) > 1 ) {
        global $wp;
        $current_url = trailingslashit( home_url( $wp->request ) );
        $menuitem_url = trailingslashit( $matches[1][0] );

        if ( str_ends_with( $current_url, $menuitem_url ) ) {
            return str_replace( 'wp-block-navigation-link', 'wp-block-navigation-link current-menu-item', $html );
        }
    }

    return $html;
}
add_filter( 'render_block_core/navigation-link', 'filter_custom_link_block', 10 );

Copy link

Hi,
This issue has gone 30 days without any activity. This means it is time for a check-in to make sure it is still relevant. If you are still experiencing this issue with the latest versions, you can help the project by responding to confirm the problem and by providing any updated reproduction steps.
Thanks for helping out.

@github-actions github-actions bot added the [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. label Jun 30, 2024
@getdave
Copy link
Contributor

getdave commented Nov 21, 2024

I've reviewed this and in WP 6.7 when you add a link to the Navigation block using the Custom Link variation it will save as type: page if you select from the search results.

<!-- wp:navigation-link {"label":"Custom Link Again","type":"page","id":2,"url":"http://localhost:8888/?page_id=2","kind":"post-type"} /-->

However, if you type the URL out (or copy/paste) manually then it will persist as a custom link and not be annotated as a page.

<!-- wp:navigation-link {"label":"Manually Added","url":"http://localhost:8888/?page_id=2","kind":"custom"} /-->
Video demonstrating different link types
Screen.Capture.on.2024-11-21.at.09-36-29.mp4

For the later scenario WordPress cannot "know" that this is an internal link without doing an operation similar to that shown in the comment above. As a result no "current" class will be applied.

We could implement something like this but it would have to be run on every single custom link in the Navigation which might have performance implications.

Given the way the Navigation block now defaults to inserting the "page" variation of the Navigation Link block, I feel it's increasingly unlikely that users will be linking to internal pages using the custom link variation.

The only scenario I can envisage is the need to accommodate internal links such as http://localhost:8888/?page_id=2#someinternalanchor where someinternalanchor is a "deep link" anchor point on the page. We don't support that in the Link UI so that may require users to work around this using the custom link.

Therefore I propose that we upgrade the Link UI to accommodate the ability to link to internal anchor points.

If there are any other work flows that I'm missing I'd be grateful if folks could let me know below in the comments 🙏

What do you think of the proposal above?

@ethanclevenger91
Copy link
Author

ethanclevenger91 commented Jan 10, 2025

As I mentioned when I opened this ticket, the pre-baked nav items in Gutenberg are not comprehensive of every possible kind of internal link that could be created. There is, for example, no block for a custom taxonomy term archive. Now perhaps it also resolves in some intelligent way (like your Page example) with more recent versions of the editor - I haven't checked. But I would offer that as another use case.

WordPress cannot "know" that this is an internal link

Classic theme navigation handled this without issue. Obviously, I'm not working on this feature, so there are nuances I don't understand, but it seems like that logic should have been maintained.

@Marc-pi
Copy link

Marc-pi commented Jan 26, 2025

  • yep, that's an annoying bug, manual link does not get the li current-menu-item class nor the aria-current="page" on a:href
    • "Given the way the Navigation block now defaults to inserting the "page" variation of the Navigation Link block, I feel it's increasingly unlikely that users will be linking to internal pages using the custom link variation." sometimes it's quicker to copy the page the url instead of searching for it (ex: WooCommerce product page with too many pages)
    • yep, the anchor link use case is also another use case
  • another anyoning thing : if you move your website from preprod to prod, you have to edit all links, the base url is not replaced (perhaps it's another issue, but Dave would like for sure to be aware of this).

@voyager131
Copy link
Contributor

I can also confirm the same behavior described above with a site I'm currently working on. Also, when a sub-menu item is selected, it appears the parent no longer gets the "current-menu-parent" class?

@wdburgdorf
Copy link

WP6.7.2, 2025 Theme, still broken.

@wdburgdorf
Copy link

The above code did not work for me. I fixed it with ChatGPT o3-mini-high:

// add current-menu-item class to custom links in navigation block
function filter_custom_link_block( string $html ): string {
    // Return early if already marked as current.
    if ( strpos( $html, 'current-menu-item' ) !== false ) {
        return $html;
    }

    // Extract the first href value.
    if ( preg_match( '/href=["\']([^"\']+)["\']/', $html, $match ) ) {
        global $wp;
        // Get the current URL.
        $current_url = home_url( $wp->request );
        $menuitem_url = $match[1];

        // Parse the menu item URL.
        $menuitem_parsed = wp_parse_url( $menuitem_url );
        // If the URL is relative (no scheme), convert it to an absolute URL.
        if ( ! isset( $menuitem_parsed['scheme'] ) ) {
            $menuitem_url = home_url( $menuitem_url );
            $menuitem_parsed = wp_parse_url( $menuitem_url );
        }

        $current_parsed = wp_parse_url( $current_url );

        // Ensure both URLs have a scheme and host and that they match.
        if (
            isset( $current_parsed['scheme'], $current_parsed['host'], $menuitem_parsed['scheme'], $menuitem_parsed['host'] ) &&
            $current_parsed['scheme'] === $menuitem_parsed['scheme'] &&
            $current_parsed['host'] === $menuitem_parsed['host']
        ) {
            // Normalize paths: if not set, treat as root ("/").
            $current_path = isset( $current_parsed['path'] ) ? untrailingslashit( $current_parsed['path'] ) : '';
            $menuitem_path = isset( $menuitem_parsed['path'] ) ? untrailingslashit( $menuitem_parsed['path'] ) : '';

            $current_path = $current_path === '' ? '/' : $current_path;
            $menuitem_path = $menuitem_path === '' ? '/' : $menuitem_path;

            // If paths match, mark as current.
            if ( $current_path === $menuitem_path ) {
                $html = str_replace(
                    'wp-block-navigation-link',
                    'wp-block-navigation-link current-menu-item',
                    $html
                );
            }
        }
    }

    return $html;
}
add_filter( 'render_block_core/navigation-link', 'filter_custom_link_block', 10 );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block Needs Testing Needs further testing to be confirmed. [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

9 participants