Tab Bar Disclosure
Code
Dependencies
- Primitives: color, spacing, border
- Assets: none (zero-JS baseline works without a script; JS is a progressive enhancement layer, not a requirement)
HTML recipe (zero-JS baseline)
<div class="ps-tab-bar" role="tablist">
<details class="ps-tab" open>
<summary class="ps-tab__summary">{{tabLabel}}</summary>
<div class="ps-tab__panel">{{content}}</div>
</details>
<!-- repeat one <details class="ps-tab"> per tab; only ONE should carry
the `open` attribute in the zero-JS default state -->
</div>
Every panel is independently expandable via native <details> behavior
with no script at all — this is the fallback, not a degraded state.
JS coordination layer
Per the recipe's own js_notes: on open, close sibling <details>
elements so only one panel is expanded at a time (true tab behavior).
Deep-linking: read window.location.hash on DOMContentLoaded, open the
<details> whose id matches, and scroll it into view.
document.querySelectorAll('.ps-tab-bar .ps-tab').forEach((detail) => {
detail.addEventListener('toggle', () => {
if (!detail.open) return;
document.querySelectorAll('.ps-tab-bar .ps-tab').forEach((sibling) => {
if (sibling !== detail) sibling.open = false;
});
});
});
const hash = window.location.hash.slice(1);
if (hash) {
const target = document.getElementById(hash);
if (target && target.matches('.ps-tab')) {
target.open = true;
target.scrollIntoView();
}
}
Only after this script runs successfully should role="tablist" /
role="tab" / role="tabpanel" / aria-selected / aria-controls be
applied (see Accessibility) — synthesising tab roles before the
coordinating JS is present breaks screen readers, since the native
<details> semantics would then be masked by roles the markup doesn't
actually behave like yet.
Important Information
Design System disclosure
This site provides open-source design tokens, documentation, and self-hostable software published by Woodfine Capital Projects Inc. Information here is for general reference only and does not constitute an offer, warranty, or a guarantee of fitness for any particular purpose. Statements regarding planned, intended, or targeted future features are forward-looking and subject to change without notice; they are not undertaken to be updated except as required by law.