Some custom code for Tabs Plugin
#1. Adding Category Filter when using Portfolio
When you use Tabs Plugin with Portfolio and need to add Filter like this.

First, add word like this into Portfolio item SEO Description
Tags: category name
for example
Tags: Digital

Next, use this code under Tabs Plugin code in Footer Injection
<!-- WM Tabs Plugin - Filter @tuanphan -->
<script>
var ALL_LABEL = "Alle";
</script>
<script>
(function () {
var style = document.createElement("style");
style.textContent = ".wm-tabs-filter-bar{display:flex;flex-wrap:wrap;gap:8px 20px;margin-bottom:16px}.wm-tabs-filter-bar button{background:none;border:none;padding:2px 0;cursor:pointer;font-size:inherit;font-family:inherit;color:inherit;text-decoration:none;position:relative;transition:opacity .2s ease}.wm-tabs-filter-bar button::after{content:'';position:absolute;bottom:0;left:0;width:100%;height:1px;background:currentColor;transform:scaleX(0);transition:transform .2s ease;transform-origin:left center}.wm-tabs-filter-bar button.active::after{transform:scaleX(1)}.wm-tabs-filter-bar button:not(.active){opacity:.5}.wm-tabs-filter-bar button:hover:not(.active){opacity:.8}";
document.head.appendChild(style);
function waitForTabs(tabsEl, callback) {
if (tabsEl.wmTabs && tabsEl.wmTabs.tabs && tabsEl.wmTabs.tabs.length > 0) {
callback(tabsEl.wmTabs);
} else {
var handler = function () {
if (tabsEl.wmTabs && tabsEl.wmTabs.tabs && tabsEl.wmTabs.tabs.length > 0) {
document.removeEventListener("wmTabs:afterOpenTab", handler);
callback(tabsEl.wmTabs);
}
};
document.addEventListener("wmTabs:afterOpenTab", handler);
}
}
async function init() {
var tabsEl = document.querySelector('[data-wm-plugin="tabs"]');
if (!tabsEl) return;
var source = tabsEl.dataset.source;
if (!source) return;
var items = [];
try {
var res = await fetch(source + "?format=json");
var data = await res.json();
items = data.items || [];
} catch (e) {
return;
}
var tagByTitle = {};
var allTags = [];
items.forEach(function (item) {
var desc = (item.seoData && item.seoData.seoDescription) || "";
var match = desc.match(/^Tags:\s*(.+)/i);
var tag = match ? match[1].trim() : null;
tagByTitle[item.title] = tag;
if (tag && allTags.indexOf(tag) === -1) allTags.push(tag);
});
if (allTags.length === 0) return;
allTags.sort();
var bar = document.createElement("div");
bar.className = "wm-tabs-filter-bar";
[ALL_LABEL].concat(allTags).forEach(function (tag) {
var btn = document.createElement("button");
btn.textContent = tag;
btn.type = "button";
if (tag === ALL_LABEL) btn.classList.add("active");
btn.addEventListener("click", function () {
bar.querySelectorAll("button").forEach(function (b) { b.classList.remove("active"); });
btn.classList.add("active");
applyFilter(tag);
});
bar.appendChild(btn);
});
tabsEl.parentNode.insertBefore(bar, tabsEl);
function applyFilter(selectedTag) {
waitForTabs(tabsEl, function (instance) {
var firstVisible = null;
instance.tabs.forEach(function (tab) {
var itemTag = tagByTitle[tab.innerText] || null;
var visible = selectedTag === ALL_LABEL || itemTag === selectedTag;
if (tab.button) tab.button.style.display = visible ? "" : "none";
if (tab.accordionButton) tab.accordionButton.style.display = visible ? "" : "none";
if (tab.selectItem) tab.selectItem.style.display = visible ? "" : "none";
if (visible && !firstVisible) firstVisible = tab;
});
if (firstVisible) instance.openTab(firstVisible.id);
});
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
</script>

To change text “Alle”, change this line
<script> var ALL_LABEL = "Alle"; </script>