Custom Top Navigation Links

:discourse2: Summary Custom Top Navigation Links allows you to add links to Discourse top navigation.
:eyeglasses: Preview Preview on Discourse Theme Creator
:hammer_and_wrench: Repository Link https://github.com/discourse/Discourse-nav-links-component
:open_book: New to Discourse Themes? Beginner’s guide to using Discourse Themes

Install this theme component

Features

Desktop

Mobile

Settings:

Name Descriptions
Nav links Semicolon delimited in this order: display name;description;URL
Hide dropdowns Hide category and tag dropdowns
Hide default links Hide the default links on both mobile and desktop.
  • Nav links — these need 3 parts:

    • Name
    • Description
    • Path or URL

    Name is the text for the link that shows up on the menu. Description shows up when you hover the name like this:

    Path/URL is where you want the link to go.

    You can add links as semicolon delimited values in theme settings following this order

    name;description;URL

    URL can also be relative like

    /c/staff, /t/232, /groups/plugin_authors, /about, /tags/official

  • Hide dropdowns

    Hides the default category and tag dropdowns

    Screenshot 2023-05-11 at 3.10.55 PM

  • Hide default links

    Hides the default links in this section

    Screenshot 2023-05-11 at 3.11.29 PM


:discourse2: Hosted by us? Theme components are available to use on our Standard, Business, and Enterprise plans.

Last edited by @JammyDodger 2024-06-11T23:40:05Z

Check documentPerform check on document:
61 Likes

Hi

I use this theme component. One of the items in the menĂş points to a category and I would like to inform the unread topics for this category.

image

Instead of Agora I would like Agora (3) for an user who has three unread topics in this category (same behaviour as standard link “Unread”).

Any idea?

Thanks in advance.

Does someone know how I could add a tag link that is actually relative to the current route? I’d like to use a tag About and offer it as a top link it to an About-topic relative to the category a user is in.

E.g. user is in category /c/feedback/7. Choosing About will direct to /tags/c/feedback/7/about.

2 Likes

I’d like to use the component on an instance but various behavior is not working:

  • When using “hide default links” it’s hiding the first two child items (Latest and Categories). But when one navigates to a category, the default “Categories”- Link is already not shown in the menu. Then this setting hides an additional navigation item, the otherwise third in line.

Screenshot from 2022-05-10 18-29-05

  • I added a menu item for a direct category link (/c/game-talk). When I navigate to it, it doesn’t get an active class and is not highlighted. Instead, the “Latest” link is highlighted and has an active class. This is not the default “Latest” link though, but one I added through the component (only linking to /latest)

  • Actually, the “Latest” link does not get an active class either when it is not named “Latest”. So the active class on the current route doesn’t seem to work at all because of the component. This is the view on /latest but with another name for the Latest-link:

1 Like

Quick question-
Trying to create this and make the url ?order=created so users can browse recent topics.

This works perfectly fine on desktop but fails on mobile- the navigation-bar just reloads and won’t show the dropdown menu.

I have same question…Is that a solution? :face_with_monocle:

I think i know why this happened…
the component has line below:

if (window.location.pathname.match(sec2)) {
          $(navHeader).html(filter + markd);
        }

Because of the reg…?itself is used as special reg mark,and the param is supposed to compare with window.location.search.
I fork the component , change it to the following code and it works.

if (sec[2].indexOf("?") === -1) {
        if (window.location.pathname.match(sec[2])) {
          $(navHeader).html(filter + markd);
        }
      } else {
        // reg ?->/?
        sec[2] = sec[2].replace(/\?/g, "/?");
        const pathWithSearch = window.location.pathname + window.location.search;
        if (pathWithSearch.match(sec[2])) {
          $(navHeader).html(filter + markd);
        }
      }
1 Like

Oh wow, well done :clap:

Where did you put this piece of code?

Discourse-nav-links-component/mobile/head_tag.html ,replace the match code. :face_with_peeking_eye:

1 Like

Why not make that a PR so that everyone can benefit?

4 Likes

Can I do that? I always think my code level is too poor…and feel a little embarrassed to do that.Thanks for the advice!!! I’ll revise it and make a PR!

1 Like

I think that about my contribution attempts too!!

However the @team (and their automated tools) seem to be pretty good at tidying code up.

Once you’ve made it a PR, you can post the PR link here in Meta and it displays an awesome embedded live update of the PR status.

5 Likes

Were you ever able to solve this? I’m having a similar problem

I can’t say I’ve found an ideal solution, but I found what the problem was for me.

The problem can be found here

Specifically, this part:

    api.modifyClass("component:navigation-item", {
      pluginId: 'discourse-nav-links-component',
      active: Ember.computed("contentFilterMode", "filterMode", function() {
        let contentFilterMode = this.get("content").get("filterMode");

        if (window.location.pathname === location) {
          return contentFilterMode === filter;
        } else {
          return this._super(contentFilterMode, this.get("filterMode"));
        }
      })
    });

It looks like this sets the “active” on each navigation link. Frankly, the logic of how it decides and what all these variables are is pretty opaque to me. But the problem is here:

        if (window.location.pathname === location) {
          return contentFilterMode === filter;
        } else {
          return this._super(contentFilterMode, this.get("filterMode"));
        }

To me, this is checking if the page URL is the same as the location of the nav bar URL, and if so it returns the result of contentFilterMode === filter, both variables being a bit unclear to me. If the condition fails, it looks like it just runs the regular logic of whether something should be marked as active (which is why my non-custom links seem to work fine). The problem is that while this code properly runs once per navigation link, the location variable always seems to be “categories” so the if statement is always false for custom links. Furthermore, even if I fix the “location” variable by replacing it with this.get("content").href, the return value is also always false because the filter variable is also always set to “categories”.

Normally I’d just do a PR to fix this, but the actual root problem still eludes me. I have come up with a workaround that works for me but slightly alters the documented functionality of this component so I’d rather not PR it. I think there will be edge cases where it doesn’t work also, like if your hompage is set to /latest

    api.modifyClass("component:navigation-item", {
      pluginId: 'discourse-nav-links-component',
      active: Ember.computed("contentFilterMode", "filterMode", function() {
        return window.location.pathname.includes(this.get("content").href);
      })
    });

Basically it just checks if the current URL includes the nav bar URL as a substring. If yes, it highlights it.

4 Likes

4 posts were split to a new topic: Custom relative tag filter on the nav bar

Hello. I iterate on this post. Is there a way to indicate unread topics please ? Thx

Hello,
How we setup open URL in new tab?
thank you!

This is potentially a really helpful component, but it seems like a few basic (but beyond my ability to dix) bugs are preventing it’s wider use. Will any of these get fixed?

Can you be more specific about which bugs are preventing you from using the component?

Yes, sorry, the main one I’ve encountered is this:

I assume it just needs some better targeted CSS but I could be wrong!

1 Like