Vertical tablist (sidebar)

A sidebar is just a tablist with aria-orientation="vertical": arrows become Up / Down, everything else is identical. CSS lays the rail beside the panels. No tree, no extra ARIA.

A wrapper for the background is added so that the optical background does not get shorter than the sidebar, but it can get higher.

Key Features

  • This is our most important feature ever!
HTML
<div role="tablist" aria-orientation="vertical" data-panelcontrol>
	<button role="tab" aria-controls="vc-1" aria-selected="true">Features</button>
	<button role="tab" aria-controls="vc-2">Pricing</button>
	<button role="tab" aria-controls="vc-3">Support</button>
</div>

<div class="background-wrapper">
	<div id="vc" data-panelset>
		<div class="panel-wrapper">
			<div class="active" id="vc-1" role="tabpanel">…</div>
			<div id="vc-2" role="tabpanel" hidden>…</div>
			<div id="vc-3" role="tabpanel" hidden>…</div>
		</div>
	</div>
</div>

Grouped sidebar: navigation, not tabs

A categorized sidebar need a bit of different handling. A tablist can not contain headings or any text as category indicator. So just do not make it a tablist. The buttons are still handled by PanelControl via data-panelcontrol, but they are normal buttons in the accessibility tree, not tabs. Tabbing through the list stops at each item, and the arrow keys do not apply.

So why not grouped tablists? Because normally, the ‘tab pattern’ uses a roving tabindex: the user uses the tab keys to get into the list, and then arrow keys navigate inside it. Two tablists means two roving islands. That is really annoying. Try it, youll see.

Account

Workspace

Key Features

  • This is our most important feature ever!
HTML
<div aria-label="Settings" data-panelcontrol>
	<h4>Account</h4>
	<button aria-controls="grp-1">Features</button>
	<button aria-controls="grp-2">Pricing</button>
	<h4>Workspace</h4>
	<button aria-controls="grp-3">Support</button>
</div>

<div id="grp" data-panelset>
	<div class="panel-wrapper">
		<div class="active" id="grp-1" role="tabpanel">…</div>
		<div id="grp-2" role="tabpanel" hidden>…</div>
		<div id="grp-3" role="tabpanel" hidden>…</div>
	</div>
</div>