Tabs
The markup
<div class="aparte-tabs aparte-tabs--underline" role="tablist" aria-label="Result view"> <button class="aparte-tabs__tab" role="tab" type="button" id="tabs-u-preview" aria-controls="tabs-u-preview-panel" aria-selected="true" tabindex="0">Preview</button> <button class="aparte-tabs__tab" role="tab" type="button" id="tabs-u-code" aria-controls="tabs-u-code-panel" aria-selected="false" tabindex="-1">Code</button></div><div class="aparte-tabs__panel" role="tabpanel" id="tabs-u-preview-panel" aria-labelledby="tabs-u-preview">What the selected tab shows.</div><div class="aparte-tabs__panel" role="tabpanel" id="tabs-u-code-panel" aria-labelledby="tabs-u-code" hidden>What the other tab shows.</div><div class="aparte-tabs aparte-tabs--segmented" role="tablist" aria-label="Theme"> <button class="aparte-tabs__tab" role="tab" type="button" id="tabs-s-light" aria-controls="tabs-s-light-panel" aria-selected="true" tabindex="0">Light</button> <button class="aparte-tabs__tab" role="tab" type="button" id="tabs-s-dark" aria-controls="tabs-s-dark-panel" aria-selected="false" tabindex="-1">Dark</button> <button class="aparte-tabs__tab" role="tab" type="button" id="tabs-s-system" aria-controls="tabs-s-system-panel" aria-selected="false" tabindex="-1">System</button></div><div class="aparte-tabs__panel" role="tabpanel" id="tabs-s-light-panel" aria-labelledby="tabs-s-light">The light theme's settings.</div><div class="aparte-tabs__panel" role="tabpanel" id="tabs-s-dark-panel" aria-labelledby="tabs-s-dark" hidden>The dark theme's settings.</div><div class="aparte-tabs__panel" role="tabpanel" id="tabs-s-system-panel" aria-labelledby="tabs-s-system" hidden>Whatever the system asks for.</div>One row of tabs, and the panel under it
Two looks, one behaviour. --underline marks the current tab with a rule beneath it
and is the quieter of the two; --segmented puts the whole row in a track and fills
the current tab, which reads as a control rather than as navigation. Neither moves
anything: aria-selected is what says which tab is current, and the app owns it.
The markup below is the whole contract of the role, and all of it is yours to write:
ONE tab stop for the list (tabindex="0" on the selected tab, -1 on the rest),
aria-controls from each tab to its role="tabpanel", and aria-labelledby back.
The app also owns the ArrowLeft/ArrowRight/Home/End handler that moves the selection
and the stop together — @aparte/plugin-artifacts’ card has a working one to copy.
A tablist without those is louder than plain buttons and says less: every tab a tab
stop, and none of them naming what it opens.
Classes
Section titled “Classes”.aparte-tabs · .aparte-tabs--segmented · .aparte-tabs--underline · .aparte-tabs__panel · .aparte-tabs__tab
The tokens these read are on the CSS variables reference; every class of the kit, on one page, is the classes reference.