Rendering lists within tabs not working
alexpaxton opened this issue · 6 comments
When I use an ordered list as a child of a tab, the active
class is not assigned to the second tab when it is active:
And here is the markdown for it:
### Lists ❌
{% tabs lists %}
{% tab lists List A %}
It doesn't like lists -- click the second tab and you won't see any text. It looks like it parses the HTML incorrectly.
1. Do this.
1. Then this.
1. Then then this.
{% endtab %}
{% tab lists List B %}
Does it work with a para first?
1. You don't see this under List B.
1. some more lists
1. moar
{% endtab %}
{% endtabs %}
Looks like my syntax is correct, not sure how to fix
Ok so I found the culprit here:
https://github.com/Ovski4/jekyll-tabs/blob/master/docs/tabs.js#L39
If you have list items within your tab content, this selector will grab them all regardless of depth. When it tries to apply .active
to the 2nd tab (for example) it applies it to the first nested tab instead of the one you'd expect.
You go from something like this:
<ul class="tab-content">
<li class="active">...</li>
<li>...</li>
</ul>
To something like this:
<ul class="tab-content">
<li>
<ul>
<li class="active"></li>
<li></li>
</ul>
</li>
<li>...</li>
</ul>
The way I fixed this was by adding a class specifically to direct children of ul.tab-content
so that I can select those and ignore any nested <li>
elements:
window.addEventListener('load', function () {
const tabLinks = document.querySelectorAll('ul.tab > li a');
// Ensure <li> els that are direct descendents of ul.tab-content have a queryable classname
const tabEls = document.querySelectorAll('ul.tab-content > li')
tabEls.forEach(tab => tab.classList.add('tab-content-item'))
Array.prototype.forEach.call(tabLinks, function(link) {
link.addEventListener('click', function (event) {
event.preventDefault();
liTab = link.parentNode;
ulTab = liTab.parentNode;
position = getChildPosition(liTab);
if (liTab.className.includes('active')) {
return;
}
removeActiveClasses(ulTab);
tabContentId = ulTab.getAttribute('data-tab');
tabContentElement = document.getElementById(tabContentId);
removeActiveClasses(tabContentElement);
tabContentElement.querySelectorAll('li.tab-content-item')[position].classList.add('active');
liTab.classList.add('active');
}, false);
});
});
Hi!
Thanks for looking into this issue, that's a good find.
I see you have a pretty good workaround. I'm thinking it would be nice to have the class tab-content-item
set by default on <li>
tags, without relying on javascript to add it to the DOM.
I'll work on patching this.
Hi @Ovski4
We're using this plugin on our site (thank you!) but are also having this problem when trying to render lists within the tabs. I've confirmed we have latest version of the tabs.js file.
A sample of the code we are using, which is causing the 2nd tab to render without any content:
{% tabs Example %}
{% tab Example Developers %}
My list:
- Item one
- Item two
- Item three
{% endtab %}
{% tab Example Users %}
Some content that is not rendering.
{% endtab %}
{% endtabs %}
Hello 👋
Sorry for the very long time to unblock this one.
I went down the rabbit hole since I coudn't reproduce your issue at first, then I realized I was using the redcarpet
markdown converter that has been deprecated and removed years from now.
I assume you are using kramdown
?
TL;DR to fix this issue, update the javascript at line 87 by adding .tab-content
to the ul
selector:
tabContentElement.querySelectorAll('ul.tab-content > li')[liPositionInUl].classList.add('active');
I can push this fix, but I'd rather make sure it works for you first. Let me know 🙏