# Better navigation for (structured) tags

**URL:** https://meta.discourse.org/t/better-navigation-for-structured-tags/206826
**Category:** UX
**Created:** [October 22, 2021, 8:15pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826 "2021-10-22T20:15:24Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![ncaming215](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ncaming215/32/205701_2.png) [@ncaming215](https://meta.discourse.org/u/ncaming215)
#### Post date: [October 22, 2021, 8:15pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/1 "2021-10-22T20:15:24Z")

</div>

Hi all,

I’m trying to ensure tags get more structured visibility in navigation, especially for those of us who rely on `Parent > Children`. We have just over 40 tags, so structured navigation for tags (which, soapbox alert, are _woefully_ underutilized by so many forums, and which Discourse excels!) is pretty vital.

Since it’s silly to add multiple menus on top of Discourse native nav, my pitch (I think?) isn’t anything too dramatic. I ugly-mocked this up as an idea …

 ![Screen Shot 2021-10-22 at 1.09.26 PM](https://global.discourse-cdn.com/meta/original/3X/0/2/02979e55519cb228ca053b11fb52f55abe8e50bb.png)

If something like this exists, I can’t find it. @Johani’s [component](https://meta.discourse.org/t/custom-hamburger-menu-links/87644) comes the closest, but unfortunately isn’t structured.

Anyway, would love any feedback, even if it’s “This doesn’t make sense” or “It took me 10 seconds to locate this on GitHub, ya newb.”

Thanks!

---

<div class="post-metadata">

### Author: ![IAmGav](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/iamgav/32/235598_2.png) [@IAmGav](https://meta.discourse.org/u/IAmGav)
#### Post date: [October 22, 2021, 8:25pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/2 "2021-10-22T20:25:30Z")

</div>

with the amount of `parent > child` tags some sites can have, they wont all fit in there.

for example: look at meta’s tags

[https://meta.discourse.org/tags](https://meta.discourse.org/tags)

---

<div class="post-metadata">

### Author: ![ncaming215](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ncaming215/32/205701_2.png) [@ncaming215](https://meta.discourse.org/u/ncaming215)
#### Post date: [October 22, 2021, 8:28pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/3 "2021-10-22T20:28:45Z")

</div>

Sympathetic to that—I’d argue [tip-toeing] meta’s example is not the best way to use tags—not that there’s any obvious best practice around tags. But even as just an _option_ for those of us who have a controlled vocabulary around tags, and rely heavily on tags (much more so than categories) this might be useful. My example was purely just that … I suspect others may have a better idea!

---

<div class="post-metadata">

### Author: ![manuel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/manuel/32/468169_2.png) [@manuel](https://meta.discourse.org/u/manuel)
#### Post date: [October 22, 2021, 8:32pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/4 "2021-10-22T20:32:47Z")

</div>

Why not just use the tags page? You could highlight the link to that page in various ways. The page itself supports structuring by groups by default.

Then you could add custom styles, either for the tags:

 ![Screenshot from 2021-10-22 21-26-05](https://global.discourse-cdn.com/meta/original/3X/2/9/2932a43ae9b073636eec3ca7e1d019aabb1aa345.png)

Or style the layout of the entire page to get a more specific presentation.

---

<div class="post-metadata">

### Author: ![ncaming215](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ncaming215/32/205701_2.png) [@ncaming215](https://meta.discourse.org/u/ncaming215)
#### Post date: [October 22, 2021, 8:38pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/5 "2021-10-22T20:38:42Z")

</div>

> [@manuel](#):
>
> Why not just use the tags page? You could highlight the link to that page in various ways. The page itself supports structuring by groups by default.
> 
> Then you could add custom styles, either for the tags:
> 
> ![Screenshot from 2021-10-22 21-26-05](https://global.discourse-cdn.com/meta/original/3X/2/9/2932a43ae9b073636eec3ca7e1d019aabb1aa345.png)
> 
> Or style the layout of the entire page to get a more specific presentation.

Yep, love the tags page—and the flexibility of the tags page. It’s great. But the tags page is not ubiquitous, whereas a menu would provide dynamic, omnipresent navigation, as it does for categories.

I suspect, like me, there’s some of us who rely far more heavily on tags than we do categories. That might seem counterintuitive, but it makes sense in certain contexts. Even the car example used in the [Tags](https://meta.discourse.org/t/a-comprehensive-guide-to-discourse-tags/121041) post would benefit from something like this. If it’s for car enthusiasts, for example, they might like hopping between tags (“`Ford` vs `Ferrari`”), rather than categories.

Then again, maybe you guys aren’t ready for this yet. But your kids are gonna love it. 😉

---

<div class="post-metadata">

### Author: ![manuel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/manuel/32/468169_2.png) [@manuel](https://meta.discourse.org/u/manuel)
#### Post date: [October 22, 2021, 9:12pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/6 "2021-10-22T21:12:09Z")

</div>

I’d be happy if you find a more dynamic solution! But I guess it would involve a serious amount of coding if you want sth that you don’t have to maintain manually. Until then I’d just make the link to the tags page more ubiquitous 😉

![Screenshot from 2021-10-22 21-57-26](https://global.discourse-cdn.com/meta/original/3X/8/5/858908d85cb1f551096735108b253e15152cdf89.png)

The other aspect that makes tags much more user-friendly in my experience are proper tag banners. I did a simple component as add-on to the tag-banners component that enables you to add descriptions to tags: [https://github.com/nolosb/discourse-tag-banners-descriptions](https://github.com/nolosb/discourse-tag-banners-descriptions)

---

<div class="post-metadata">

### Author: ![JonathanShaw](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jonathanshaw/32/532672_2.png) [@JonathanShaw](https://meta.discourse.org/u/JonathanShaw)
#### Post date: [October 23, 2021, 7:46am UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/7 "2021-10-23T07:46:41Z")

</div>

A slightly different direction: I’ve made tag rendering on topics and in topic lists show hierarchy breadcrumb-style: "parent \> child’ instead of “child, parent”.

My solution was somewhat site-specific and rather hacky, but the end result is pleasing.

The biggest obstacle to what I did, and what you want to do, is that discourse doesn’t preload the tag groups so they’re not available when you need them without making an API request. I think it should, in the same way that the category structure is preloaded.

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [October 23, 2021, 6:52pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/8 "2021-10-23T18:52:41Z")

</div>

The issue here is a space limitation and not a technical limitation.

> [@ncaming215](#):
>
> We have just over 40 tags

as noted here

> [@IAmGav](#):
>
> with the amount of `parent > child` tags some sites can have, they wont all fit in there

Imagine your experience as a user; if you open a menu on a website, it looks like this.

You’d be overwhelmed, to say the least. Especially since that menu doesn’t have a search function to help you narrow down the results.

So, let’s try to find the middle ground between what you want to do and what users want to experience. How do we do that? We show a limited number of tag groups and indicate that there are more to look at. So, something like this:

 ![hamburger menu tags](https://global.discourse-cdn.com/meta/original/3X/2/f/2fed1702ac0a7f77acdecf39d7b90d4bd4a61692.png)

So, how do you do that?

Here’s the code:

```xml
<script type="text/discourse-plugin" version="0.8">
const MAX_TAGS_TO_SHOW = 20;
const Category = require("discourse/models/category").default;
const siteSettings = api.container.lookup("site-settings:main");
const tagStyle = siteSettings.tag_style;

const getNumberOfTags = (tags, categoryTagsGroups) => {
  let count = 0;
  count = tags.length;
  for (const categoryTagsGroup of categoryTagsGroups) {
    count = count + categoryTagsGroup.tags.length;
  }
  return count;
};

fetch("/tags.json")
  .then(response => response.json())
  .then(data => {
    try {
      const tags = data.tags;
      const hasCategoryTagGroups = data.extras?.categories;

      if (hasCategoryTagGroups) {
        const categoryTagsGroups = data.extras.categories;
        let moreCount = getNumberOfTags(tags, categoryTagsGroups);
        let visibleCount = 0;

        const content = [];
        for (const categoryTagsGroup of categoryTagsGroups) {
          const category = Category.findById(categoryTagsGroup.id);
          const name = category.name;
          const childTags = categoryTagsGroup.tags;
          const childTagNodes = [];

          childTags.forEach((tag, index) => {
            if (visibleCount <= MAX_TAGS_TO_SHOW) {
              childTagNodes.push(
                api.h(
                  "li.tag-link-item",
                  api.h(
                    `a.discourse-tag.tag-link.${tagStyle}`,
                    { href: `/tag/${tag.text}` },
                    tag.text
                  )
                )
              );
              moreCount--;
              visibleCount++;
            }
          });

          if (childTagNodes.length) {
            content.push([
              api.h("li.heading", api.h("span", name)),
              childTagNodes
            ]);
          }
        }

        api.decorateWidget("menu-links:after", helper => {
          if (helper.attrs.name !== "general-links") return;
          return api.h("div.clearfix", [
            api.h("ul.tag-links", [
              api.h("a.categories-link", { href: "/tags" }, [
                "Tags ",
                moreCount ? `(${moreCount} more)...` : ""
              ]),
              content
            ]),
            api.h("hr")
          ]);
        });
      }
    } catch (error) {
      console.error("There's an issue in the hamburger tags theme component");
      console.error(error);
    }
  })
  .catch(console.error);

</script>

```

This goes in the `header` tab of your theme. You can change

```javascript
const MAX_TAGS_TO_SHOW = 20;

```

at the top to the number of tags you want to show.

Then all you need to add is a bit of CSS to style the links. Here’s something basic to get you started.

```scss
.tag-links {
  .heading {
    padding: 0.25em 0.5em;
  }
  .tag-link-item {
    background-color: transparent;
    display: inline-flex;
    align-items: center;
    padding: 0.25em 0.5em;
    width: 50%;
    box-sizing: border-box;
    .tag-link {
      display: inline-flex;
      width: 100%;
      &:hover {
        color: var(--primary);
      }
    }
  }
}

```

Note that the javascript above will respect the tag style set in your site settings. Also, if your site relies very heavily on tags, then you probably don’t need to have the categories visible in that menu. Hiding them would help reduce user confusion.

Also, if you add an expanded tags section, then this link becomes redundant.

 ![default tags link in hamburger menu](https://global.discourse-cdn.com/meta/original/3X/9/7/97b7513bc6a8e9fdd12470edad8ac8312ba2fac0.png)

So, let’s hide them with something like this.

```scss
.panel-body {
  .category-links,
  .categories-separator,
  .widget-link[href="/tags"] {
    display: none;
  }
}

```

Finally, as noted here:

> [@JonathanShaw](#):
>
> The biggest obstacle to what I did, and what you want to do, is that discourse doesn’t preload the tag groups so they’re not available when you need them without making an API request

This data is not passed to the client by default unless you visit the `/tags`, so the code above adds an additional request on the homepage (runs only once per visit). Discourse tries to keep things very simple, so, unless the data is necessary, it won’t load it by default.

I don’t see this being added to Discourse core any time soon. So an extra request is pretty much your only choice here unless you want to write a plugin that runs on the server.

---

<div class="post-metadata">

### Author: ![ncaming215](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ncaming215/32/205701_2.png) [@ncaming215](https://meta.discourse.org/u/ncaming215)
#### Post date: [October 26, 2021, 10:20pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/9 "2021-10-26T22:20:49Z")

</div>

Thanks, Joe, this is fantastic!

A couple quick things … I saw that your original response pulled in by tag group (instead of child tags). Any reason for that? I couldn’t get the child tags to surface, but _did_ have luck with your initial response using the tag group.

The _only_ issue is that the tags aren’t visible to logged out users. I’m assuming this is API related? Any way around that?

Otherwise, this is a god-send—I can certainly see others using this code. Thank you so much!

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [October 27, 2021, 8:37pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/10 "2021-10-27T20:37:11Z")

</div>

I created a theme component that should make this a little bit easier. You pick between

1. nested tag groups
2. nested allowed category tags
3. flat top tags

More details here

> [@Discourse hamburger tags](https://meta.discourse.org/t/discourse-hamburger-tags/207299):
>
> This is a theme component that will allow you to add tags to the hamburger menu easily. The component comes with three display options. Samples: Nested tag groups Nested allowed category tags Flat top tags (across the site) Settings: The component comes with seven settings. The hamburger\_menu\_tags\_mode allows you to set the view mode you prefer. top tags: shows a flat list of the top tags used o…

---

<div class="post-metadata">

### Author: ![ncaming215](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ncaming215/32/205701_2.png) [@ncaming215](https://meta.discourse.org/u/ncaming215)
#### Post date: [October 27, 2021, 8:48pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/11 "2021-10-27T20:48:27Z")

</div>

> [@Johani](#):
>
> I created a theme component that should make this a little bit easier. You pick between
> 
> 1. nested tag groups
> 2. nested allowed category tags
> 3. flat top tags
> 
> More details here  
> [Discourse hamburger tags](https://meta.discourse.org/t/discourse-hamburger-tags/207299)

I nominate Joe as Patron Saint of Discourse.

---

<div class="post-metadata">

### Author: ![IAmGav](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/iamgav/32/235598_2.png) [@IAmGav](https://meta.discourse.org/u/IAmGav)
#### Post date: [October 27, 2021, 8:50pm UTC](https://meta.discourse.org/t/better-navigation-for-structured-tags/206826/12 "2021-10-27T20:50:54Z")

</div>

hahaha, i was busy creating one as well for my training course.

darn.

thanks anyway
