Most Figma libraries do not fail because of bad taste. They fail because of duplication. Figma's own guidance shows that component properties can collapse dozens of near identical layers into one flexible component (Figma - Create and manage component properties). I have rebuilt libraries where a single button existed as 60 separate frames. Sixty. After a properties rewrite it was one component set with two variants and three properties. Same coverage, a fraction of the maintenance.
This guide is about the four tools that decide whether your components scale: variants, auto layout, component properties, and the slots pattern. Get the split right and updates take minutes. Get it wrong and every design token change becomes a scavenger hunt.
When should you use variants versus separate components?
Use variants for states of the same object, and separate components for genuinely different objects. Figma lets a single component set hold many variants organized by named properties like Size or State (Figma - Create component variants). That power gets abused constantly. A variant set should read like a small, obvious grid, not a junk drawer.
Here is the test I run. Could these two things ever swap into the same spot on a screen? A primary and secondary button, yes. A button and a dropdown, no. If the answer is no, split them.
- Same object, different state: use variants (default, hover, disabled)
- Different content, same shape: use a component property
- Genuinely different UI element: separate components entirely
I once inherited a set called "Element" with 84 variants. Cards, chips, and tags all crammed together. Nobody could find anything. We broke it into three components and the panel finally made sense.
How do component properties cut duplication?
Component properties let one variant carry variable content, which is where the real duplication savings live. There are four types worth knowing: boolean, text, instance swap, and variant. On a typical button I use a boolean to toggle a leading icon, a text property for the label, and an instance swap so the icon itself is exchangeable without a new draw.
Boolean and text properties
Booleans show or hide layers. Text properties expose editable strings directly in the right panel, so nobody double clicks four layers deep to change a label. Small thing, huge time saver. On a notification component I expose the title text, the body text, and a boolean for the dismiss button. That single component covers what used to be nine frames.
Instance swap properties
Instance swap is the quiet hero. It lets a consumer replace a nested instance from a dropdown, so one card can host any icon in your set. This is also the mechanism behind slots, which I will get to.
How does auto layout keep components responsive?
Auto layout is the resizing engine that makes a component adapt instead of shatter when content changes. Set a frame to hug or fill, define padding once, and children reflow automatically. My default button uses 12 pixels vertical and 16 horizontal padding, hug height, and a label set to fill.
Nesting is the part people skip. A card is really three stacked auto layout frames: header, body, footer, each with its own gap. Set each child's resizing on purpose.
- Fixed: avatars, icons, anything with a locked dimension
- Hug: labels and tags that should shrink to their content
- Fill: text blocks and containers that should stretch
Do you really need a 320 pixel and a 480 pixel version of the same card? Usually not. One auto layout card handles both widths.
What is the slots pattern and why does it matter?
The slots pattern uses an instance swap on a placeholder frame so a wrapper component owns layout while consumers supply content. Think of a modal that controls padding, max width, and shadow, but exposes a Content Slot you fill with anything. I build one shell instead of a dozen modal variants.
This is my favorite pattern for maintainability at scale, and I will say something a little contrarian: most teams over build variants and under use slots. Slots keep wrapper logic in exactly one place. Change the modal shadow once, every modal follows. The cost is discoverability, so name the property clearly and ship two or three starter instances.
Nesting slots inside slots gets fragile fast, though. I cap it at two levels. Beyond that, debugging why a padding value is not applying eats an afternoon, and I have lost that afternoon more than once.
Keeping libraries maintainable
Maintainability comes down to fewer, smarter components rather than more clever ones. Every extra variant is a future edit multiplied across the file. Before adding one, ask whether a property covers it. Before adding a component, ask whether a variant covers it.
The libraries I trust share three habits. Named properties that read plainly. Auto layout on every container. Slots for wrappers instead of endless variants. Do that and your files stop breaking under their own weight, and a design token update ripples through your whole product in one pass, not fifty.
Components are the layer your tokens ride on, so wire them into a real pipeline with design tokens from Figma to code. If you're assembling the whole library from scratch, the step-by-step design system guide covers the structure around them, and a handful of Figma plugins that save time speed up the repetitive parts of building variants. If a stakeholder is pushing a simpler tool instead, the Canva vs Figma comparison shows why components like these don't exist there. And once the library is built, the designer to developer handoff playbook turns those variants into specs engineers can ship.