Skip to content

Extending

The grammar your own components follow to stay on-system.

Extending keel — the grammar

New components follow the same contract the shipped ones do:

  • Names follow k-block__element--modifier (BEM) — drop the k- prefix for your own so it's clear what shipped and what didn't.
  • Components consume tokens, never raw values. No hex colors, no pixel paddings — every visual decision points at the tokens layer, so your component rethemes with the rest of the page.
  • Expose your own knobs with token defaults — var(--my-knob, var(--k-token)) — so others can retheme your component the same way you retheme keel's.

A complete worked recipe — a testimonial component, defined in this page's own style block and rendered live below:

.testimonial {
  background: var(--k-surface);
  border: 1px solid var(--k-border);
  border-radius: var(--k-radius-l);
  padding: var(--k-space-5);
}
.testimonial__quote {
  font-size: var(--k-text-l);
  color: var(--k-text-soft);
  margin: 0 0 var(--k-space-3);
}
.testimonial__name {
  font-family: var(--k-font-mono);
  font-size: var(--k-text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--k-text-faint);
}

Twelve lines of CSS, and it already looks like it shipped with the framework — because it's written in the same words.

a satisfied prototype

This is the same grammar keel itself is written in; read keel.css and you already know how to extend it.

What's missing

keel ships zero JavaScript, so anything that needs a script is deliberately absent. Dropdowns, tooltips, and toasts used to be on this list — native details, a CSS attribute, and popover now cover them above, trade-offs stated. What's still missing:

  • No tab panels. .k-tabs ships the bar, but there is no accessible zero-JS panel-switching pattern keel is willing to ship. Point the tabs at separate pages, use a .k-accordion, or write the three lines of JavaScript yourself. (Carousels used to be on this list too — .k-gallery now covers them with native scroll-snap.)
  • No form submission handling. keel styles fields and validation states; what happens on submit — client-side or otherwise — is yours.
  • No modal-trigger JS. The base layer styles dialog and .k-drawer; the one line of showModal() wiring is yours to write.