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.