design tools

Component Variant

A component variant is a prop that switches one component between distinct visual identities defined in the design system. In every TSX file the variant appears as a union of string literals in the TypeScript props type. Those literals feed a mapping object that applies the correct Tailwind classes or CSS variables. The pattern copies Figma variants exactly. Designers read the variant block first then the size scale then the color mappings. This scan reveals the full range of options the component supports in production. Stripe standardized on four button variants in 2026. Primary delivered a filled blue background with white text and a hover state that darkened the blue by one step on the token scale. Secondary used a white background with a gray border. Ghost removed the background entirely. Destructive switched the colors to red tokens. Every value came from the central tokens file so no hex codes appeared in the component. The same component powered CTAs in marketing campaigns and inline actions in the dashboard. One file replaced the old set of seven separate button components. Teams that adopted this approach cut their component library maintenance time in half. The best variant systems pull from a shared variants.ts file so Button and Badge stay perfectly aligned on color and radius tokens.

A component variant is not scattered Tailwind classes applied ad hoc throughout the JSX. It is not the children prop that injects text or icons. It is not the conditional rendering that swaps a spinner for content based on an isLoading boolean. It is not any useState hook useEffect block async function or API call. Those remain engineering decisions that designers read once then ignore. The variant lives only in the type definition and the class mapping at the top of the file. It selects the design surface. It does not manage logic or data. Designers who mistake a ternary for a variant add unnecessary complexity. They learn to push for explicit variants for every state instead of hidden conditionals that ship without designed counterparts.

The Button component in Linear 2025 offers a concrete example. Its props type listed variant as primary secondary ghost or destructive and size as sm md or lg. The return statement applied classes through cn from tailwind-merge and cva. Primary combined bg-blue-600 text-white hover:bg-blue-700 focus:ring-2. Ghost combined text-gray-500 hover:bg-gray-100. The designer opened the file ran the five glance scan and immediately saw the variant object. It matched the Figma master component except for the missing destructive option in one frame. The PR comment read add the destructive variant using color-destructive-600 from tokens to match the Figma file we updated last week. The engineer applied the change in minutes. The same pattern appeared in the Table component at Shopify. Row variants included default striped and highlighted. The highlighted variant applied bg-amber-50 border-l-4 border-amber-400. When the AI prompt extracted the visual states the designer discovered the striped variant lacked proper dark mode support. They requested the addition of dark:bg-zinc-900 and the update shipped with the next release. A third example is the Modal component at Vercel. It supported size variants full and compact plus a variant called dismissible that added the escape key handler note in comments. The prompt compare this component to the attached Figma frame listed three spacing mismatches that the team fixed before merge. The FormInput at Dropbox followed the same structure with default compact inline and withIcon variants where the inline version dropped labels and used text-base from the strict type scale to fit inside tight dashboard headers.

Use component variants when you review any frontend PR when you build new Figma components that must match code and when you run your weekly code literacy exercise on a real file from the codebase. Insert them into the 12 point checklist as the gate that confirms every visual state has a corresponding variant or conditional mapped to a designed frame. Pair the concept with the three Claude prompts to surface mismatches in seconds and to generate the Figma spec automatically. Apply them at scale across large libraries like Primer at GitHub or Polaris at Shopify where hundreds of components must stay in sync. Reach for them to argue for design system improvements in planning meetings by showing concrete gaps between the TSX variants and the production Figma library. The tactic scales. A designer who masters variants on buttons quickly moves to cards navigation tabs and form elements. Within a month the entire frontend surface becomes legible. The organization gains faster reviews and fewer visual regressions in production.

Never use component variants when the needed change requires new child elements or a different semantic HTML tag. Create a new component in that case. Avoid them when the variant count exceeds eight because the cognitive load on both designers and engineers grows too high. Do not touch the variant mapping code in PRs if the change involves hooks or server logic. Write the comment instead and let the engineer implement. Skip formal variants on temporary campaign pages that live outside the core library. Hard coded classes suffice there and keep the shared components clean.

Component variants let designers read production code like their own Figma files and catch every mismatch before it reaches users.

Related terms

Keep exploring