The issue here is a space limitation and not a technical limitation.
as noted here
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:
So, how do you do that?
Here’s the code:
<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
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.
.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.
So, let’s hide them with something like this.
.panel-body {
.category-links,
.categories-separator,
.widget-link[href="/tags"] {
display: none;
}
}
Finally, as noted here:
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.