SkillByAIOpen interactive version →

Lesson 18 / 25

Extracting Reusable Components

Reuse markup, not CSS classes.

Components, partials and loops

Long class lists are manageable when they live in one place: a React, Vue, Svelte or Angular component, a server-side template partial, or a loop in your markup. Pass variants as props and map them to complete class strings. Multi-cursor editing helps for small repeated snippets. Only reach for @apply or custom CSS classes when no component system exists.

A React Button component

Variants mapped to complete class names.

const base = "inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-semibold " +
  "focus-visible:outline-2 focus-visible:outline-offset-2 disabled:opacity-50";

const variants = {
  primary: "bg-cyan-600 text-white hover:bg-cyan-700 focus-visible:outline-cyan-600",
  secondary: "border border-gray-300 bg-white text-gray-900 hover:bg-gray-50",
  danger: "bg-red-600 text-white hover:bg-red-700 focus-visible:outline-red-600",
};

export function Button({ variant = "primary", className = "", ...props }) {
  return <button className={`${base} ${variants[variant]} ${className}`} {...props} />;
}

Keep variant maps exhaustive

Complete class strings in a lookup object keep them detectable by Tailwind and easy to review.

Quick check: What is the recommended way to reuse a styled button across a React app?

  • Create a Button component that holds the classes
  • Copy the class list everywhere
  • Build class names from string fragments
  • Use inline style objects only
Answer

Create a Button component that holds the classes — Reuse markup through components.