Picture a component library with three separate props doing the exact same job: buttonStyle, buttonType, and btnVariant. Three engineers, three sprints, zero conversation. Untangling it takes most of a week nobody has.
TL;DR: Prop naming is the actual API of your design system, and inconsistency compounds fast. Modern conventions favor a single semantic
variantprop over competing names liketypeorkind, kept separate from unrelated concerns likesize, so the system stays predictable as it grows.
Why Does Prop Naming Matter More Than It Looks Like It Should?
Because a design system's real API isn't its visuals, it's the names an engineer has to remember every single time they use a component. Get that wrong and every consumer pays a small tax, forever. Get it right once and the tax disappears for every component built after.
A Button with variant and a Badge with type doing the identical job forces developers to look up which word applies to which component, every time, for the life of the system. That's not a nitpick. Multiply it by every engineer, every day, across years of a product's life, and it's real, measurable friction that shows up as slower PRs and more Slack questions than it should.
Variant vs Type vs Kind: Which One Actually Wins?
variant, and it's not close anymore. It's the name shadcn/ui made close to a default across the React ecosystem, paired with Class Variance Authority (CVA) to keep the values type-safe (Vercel Academy, 2026). Reserve type for genuine HTML semantics, an <input type="email"> or a <button type="submit">, where the browser already owns that word's meaning. Don't reuse it for your own style variations; you'll fight the native attribute forever.
kind shows up in older systems and it rarely earns its place. It's usually a synonym somebody reached for because they didn't check what the rest of the system already used. If you're starting fresh, pick variant. If you're inheriting kind everywhere, that's a real migration to plan, not a debate to keep having per component.
| Name | What it should mean | When to use it |
|---|---|---|
variant | Visual style options (default, destructive, outline, ghost) | Every component with visual style variations |
type | Native HTML semantics (input type, button type) | Only where the browser already owns the word's meaning |
kind | No settled meaning | Avoid; usually a sign nobody checked existing convention |
A prop name is a promise. Break the pattern once and every engineer starts checking twice.
How Do You Keep One Prop From Doing Two Jobs?
Watch for values that secretly combine two concerns, primary-large, secondary-small, destructive-compact. That's a size and an intent smashed into one enum, and it multiplies badly: three intents times three sizes is nine values to maintain instead of two small, independent props.
Split them. variant="primary" plus size="lg" lets consumers combine values freely and lets you add a new size without touching every variant definition. The test I use on every prop review: if describing its job needs the word "and," it's already two props that haven't been separated yet.
What Does This Look Like in Practice?
type ButtonProps = {
variant?: "primary" | "secondary" | "destructive" | "ghost";
size?: "sm" | "md" | "lg";
isDisabled?: boolean;
isLoading?: boolean;
};
Notice the booleans read like yes-or-no questions: isDisabled, isLoading, never a vague state string or a negative like isNotVisible. Double negatives in conditional logic are exactly the kind of bug that slips past review, so name the positive case and flip the default instead. If your docs render prop names in a code face, monospace fonts for product UI compares IBM Plex Mono, JetBrains Mono and Berkeley Mono for that job.
How Do You Stop New Components From Breaking the Pattern?
Write the convention down once, in one file everyone can find, and enforce it with a lint rule if your stack supports one. A documented convention that lives only in a senior engineer's memory doesn't survive that engineer taking a two-week vacation. This is also where a clean designer to developer handoff pays off twice: if the Figma variant names already match variant, size, and isDisabled character for character, there's no translation step where a new name could sneak in.
The same discipline applies inside Figma itself. When you build components with variants and auto layout, name the variant properties the exact same way you'll name the code props. A Figma property called "State" that maps to a code prop called variant is a mismatch waiting to cause a bug report six months from now, and nobody will remember why the two got out of sync.
My honest take: naming conventions feel like bikeshedding until you're the one untangling three duplicate props at 11pm before a release. Spend the hour agreeing on one word early. It's cheaper than every hour you'll spend cleaning up after skipping it.
What Should a New Design System Do From Day One?
Write a one-page naming contract before the first component ships, not after the third team has already picked its own convention. List the props every interactive component will share, variant, size, isDisabled, isLoading, and the exact values each one accepts. Put it next to your token documentation, not buried in a wiki nobody opens.
Then hold the line. The hardest part isn't deciding on variant over kind, it's saying no to the fourth engineer who wants buttonStyle because it's "just this one component." That single exception is how you end up back at three duplicate props a year later. A naming contract only works if it applies to the component nobody wants to slow down for too. A contract engineers route around is a design system adoption problem in miniature, and that one gets solved with fast responses and visible backing, not with a longer wiki page. You can also check the contract with numbers instead of opinions: a design system health scorecard counts how many imports and tokens actually follow it.