Navigation
Getting around — the header, the trail, the page links, the closing band.
Responsive nav (burger)
keel's honest answer to the hamburger: the menu is a
.k-drawer — a real modal dialog — so
the focus trap, Esc, and the backdrop are the platform's, not a
script's. Opening it is the one line of JavaScript on the
button: showModal(). Closing needs none — the
close button sits in a form method="dialog". The
trigger is a .k-btn--icon with the built-in
.k-icon--menu; it's icon-only, so the
aria-label is not optional. On wide screens you
don't collapse anything clever — you simply show the links and
hide the button, one utility each:
.k-desktop-only on the link list,
.k-mobile-only on the burger.
Markup
<nav class="k-nav" aria-label="Site">
<a class="k-nav__brand" href="../index.html">brand</a>
<!-- wide screens: just show the links -->
<ul class="k-nav__links k-desktop-only">
<li><a href="docs.html">Docs</a></li>
<li><a href="pricing.html">Pricing</a></li>
</ul>
<!-- small screens: the burger, one line of JS -->
<button class="k-btn k-btn--icon k-btn--ghost k-mobile-only" type="button"
aria-label="Menu"
onclick="document.getElementById('site-menu').showModal()">
<span class="k-icon k-icon--menu" aria-hidden="true"></span>
</button>
</nav>
<dialog class="k-drawer" id="site-menu" aria-label="Menu">
<h4>Menu</h4>
<ul class="k-menu">
<li><a href="docs.html">Docs</a></li>
<li><a href="pricing.html">Pricing</a></li>
</ul>
<form method="dialog">
<button class="k-btn k-btn--ghost">Close</button>
</form>
</dialog>
Tabs
.k-tabs is the visual tab bar — a row of links
or buttons on a baseline rule, scrolling sideways if it
overflows. The active tab is marked with
aria-current (or aria-selected="true"
in a scripted ARIA tabs widget) and gets the accent underline —
the visual state is the accessibility state. Honestly: keel
ships the bar, not the panel switching. Point the tabs at
separate pages, use a .k-accordion instead, or
write the three lines of JavaScript yourself.
Markup
<ul class="k-tabs">
<li><a href="overview.html" aria-current="true">Overview</a></li>
<li><a href="activity.html">Activity</a></li>
<li><a href="settings.html">Settings</a></li>
<li><a href="billing.html">Billing</a></li>
</ul>
For a lighter look, .k-tabs--pill drops the
baseline rule and turns each tab into a chip. The active tab —
aria-current or aria-selected="true" —
fills with a soft accent instead of gaining an underline; the
rest tint on hover. Same markup, same accessibility state, a
different shape.
Markup
<ul class="k-tabs k-tabs--pill">
<li><button type="button" aria-selected="true">Overview</button></li>
<li><button type="button">Activity</button></li>
<li><button type="button">Settings</button></li>
<li><button type="button">Billing</button></li>
</ul>
Segmented control
.k-segmented is a compact pill track holding a
few buttons (or radios); the active segment fills with a raised
surface "thumb". Mark it with aria-pressed="true" on
a button, aria-checked="true" on a radio, or
.is-active — the visual state is the accessibility
state. It's the more compact, single-choice cousin of the
bordered .k-btn-group and of tabs: where
.k-tabs switch page-level views, this is a small
inline toggle for one setting. It's chrome only — your JavaScript
(or radios in a form) tracks the selection.
Markup
<div class="k-segmented" role="group" aria-label="View">
<button type="button" aria-pressed="false">Day</button>
<button type="button" aria-pressed="true">Week</button>
<button type="button" aria-pressed="false">Month</button>
</div>
Pagination
.k-pagination is a row of page links. The
current page gets aria-current="page", which keel
fills with the accent — again, the visual state is the
accessibility state.
Markup
<nav aria-label="Pagination">
<ul class="k-pagination">
<li><a href="?p=1">1</a></li>
<li><a href="?p=2" aria-current="page">2</a></li>
<li><a href="?p=3">3</a></li>
<li><span>…</span></li>
<li><a href="?p=9">9</a></li>
</ul>
</nav>
Skip link
The first focusable thing on a page should let keyboard
users jump past the header:
<a href="#main">Skip to content</a> as
the first child of body. Honestly:
.k-visually-hidden alone keeps it hidden
even on focus — which defeats the point. Either pair it
with a three-line :focus reveal of your own (the
recommended pattern below), or skip the hiding entirely and put
the link visibly in a .k-banner.
Markup
<body>
<a class="k-visually-hidden skip-link" href="#main">Skip to content</a>
…
<main id="main">…</main>
<style>
/* your CSS — reveal it when it's focused */
.skip-link:focus {
position: fixed; inset: var(--k-space-2) auto auto var(--k-space-2);
inline-size: auto; block-size: auto; margin: 0; clip-path: none;
}
</style>