6 · Component recipes

Lesson 6 of 8 — name a group of rules once in the config and reuse it everywhere, with variants.

1 min readv1

The button from lesson 1 has twelve rules. You do not want to repeat them. A recipe gives them a name.

You will learn: defining recipes · extending one recipe from another · overriding per instance · applying a recipe at a breakpoint.

Define a recipe#

TypeScript
// nibcss.config.ts
export default defineConfig({
  tokens: { /* from lesson 5 */ },
  components: {
    btn: "d=inline-flex; ali=center; jsc=center; g=8px; p=10px 18px; bd=none; bdrd=$radius.md; ftw=600; cur=pointer; ts=all .15s; focus-visible:otl=3px solid #A8ABF4; focus-visible:otlo=2px; disabled:opc=.5",
    "btn-primary": "btn; bgc=$color.brand; cl=#fff; hover:bgc=$color.brand-hover",
    "btn-outline": "btn; bgc=transparent; cl=$color.brand; bd=1px solid $color.border; hover:bgc=#EEEFFE",
  },
});

A recipe is written in exactly the same syntax as an attribute. A name with no = is a recipe reference, so btn-primary includes everything in btn and adds its own colours.

Use it#

HTML
<div nib="d=flex; g=10px; flxw=wrap">
  <button nib="btn-primary">Primary</button>
  <button nib="btn-outline">Outline</button>
  <button nib="btn-ghost">Ghost</button>
</div>

Override per instance#

Rules after a recipe add to it, and a later rule for the same property wins:

HTML
<button nib="btn-primary; w=100%; mt=16px">Full-width primary</button>

Recipes and modifiers#

A modifier before a recipe applies to every rule inside it:

HTML
<!-- The card styles only apply from 768px up -->
<article nib="md:card">…</article>

One class per recipe#

However many rules a recipe contains, the element gets one class for it, so markup stays clean in DevTools.

When to make a recipe#

  • The same group of rules appears in three or more places.
  • It represents a concept designers name: button, card, badge, input.
  • You want to change it everywhere at once.

Keep one-off layout on the element (mt=24px, gc=span 2) — recipes are for identity, not position.

Next steps#