Feature request: UI component API for tabs
See original GitHub issueIs your proposal related to a problem?
We’ve recently re-implemented Wagtail’s tabs from a legacy Bootstrap widget, to a bespoke implementation following established patterns. One thing we haven’t been able to do as part of this re-implementation is creating a UI component API so tabs are easy to reuse without copy-pasting code. Right now, reusing tabs is still hard and error-prone.
Describe the solution you’d like
We should have a tabs
template tag or equivalent, like we have {% icon name="rocket" %}
. This would make it possible to reuse Wagtail’s tabs across the CMS admin, in core and in third-party packages, with the implementation details hidden behind the scenes.
A blocker for this is that Django templates has no built-in support for passing template fragments to template tags. We would need to either leverage a library that does this, or create our bespoke implementation. Here are potential candidates, which we can either choose to reuse as-is or learn from their implementations:
- django-components – Reusable UI components for Django, going further than template partials.
- django-component – Modern components for django templates Declarative and composable components inspired by javascript frameworks.
- slippers – Reusable components for Django, without writing a single line of Python.
Describe alternatives you’ve considered
Copy-paste HTML
This is what to copy-paste currently – we deliberately kept the markup simple so this isn’t too bad, but not good enough:
<div class="w-tabs" data-tabs data-tabs-animate>
<div role="tablist" class="w-tabs__list">
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with tab_id='one' title='Tab 1' errors_count='5' %}
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with tab_id='two' title='Tab 2' %}
</div>
<section
id="tab-one"
class="w-tabs__panel"
role="tabpanel"
aria-labelledby="tab-label-one"
>
Here are tab 1’s contents.
</section>
<section
id="tab-two"
class="w-tabs__panel"
role="tabpanel"
aria-labelledby="tab-label-two"
>
Here are tab 2’s contents.
</section>
</div>
Template components
Within Wagtail, there is also the concept of template components which might be a good fit, though there’s been no need to create tabs from Python so far so it’s not that clear-cut.
This might support our use case, but would require quite a significant refactoring which doesn’t feel desirable (unless we did a template component and a template tag.
Additional context
Here is pseudo-code of what the API could look like:
{% tabs %}
{% slot "tablist" %}
{% tab tab_id="one" title="Tab 1" %}
{% tab tab_id="two" title="Tab 2" %}
{% /slot %}
{% slot "tabpanels" %}
{% tabpanel tab_id="one" %}
Here are tab 1’s contents.
{% /tabpanel %}
{% tabpanel tab_id="two" %}
Here are tab 2’s contents.
{% /tabpanel %}
{% /slot %}
{% /tabs %}
Or something like:
{% tabs %}
{% tab tab_id="one" title="Tab 1" %}
Here are tab 1’s contents.
{% /tab %}
{% tab tab_id="two" title="Tab 2" %}
Here are tab 2’s contents.
{% /tab %}
{% /tabs %}
References:
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:10 (9 by maintainers)
Top GitHub Comments
Thanks @zerolab - I have a fix for that issue up https://github.com/wagtail/wagtail/pull/8794
Flagging as something for us to revisit once Stimulus (#9075 / #9337) lands.