Introduction: A Small UI Hero
Buttons are deceptively simple. They’re everywhere in UI—signups, shopping carts, settings—but they’re also packed with complexity: tokens, variants, states, icons, accessibility, responsiveness. A good button is more than just a rectangle with text.
In this deep dive, we’ll build a modern, scalable button in Figma—from design token foundation to smart, stateful interactions—so you can reuse and adapt it confidently across your design system.

1. Start with the Design Tokens
Before drawing anything, define the design language your button will follow:
- Color tokens:
color.button.primary.bgcolor.button.primary.textcolor.button.hover.bg
- Typography tokens:
font.button.labelorfont.label.md
- Spacing tokens:
space.button.padding.horizontal/vertical
- Radius:
radius.button.sm
- Shadow or elevation:
elevation.button.default/pressed
🧠 These tokens create consistency—and plug directly into code via Figma Variables.
2. Build the Base Shape with Auto Layout
Use Figma’s Auto Layout on the main frame:
- Direction: Horizontal
- Alignment: Center
- Padding: From token (
space.button.padding) - Gap: Token or fixed (e.g. 8px between icon and label)
- Corner Radius: Token-driven
- Sizing:
- Width: Hug
- Height: Hug or Fixed (depending on your scale system)
✅ Add min-width padding if you want buttons to remain legible even with short text.
3. Add Label and Optional Icon
Inside the frame:
- Add a Text layer for the label
- Font from token
- Line height: 100%
- Add an Instance Swap slot for an icon (optional)
- Use a Boolean property to toggle icon visibility
- Allow icon on left, right, or both via instance or variant
📎 Bonus: Use naming like iconLeft, iconRight, hasIcon for clarity.
4. Define Component Properties
Add smart flexibility:
Size: Small / Medium / LargeState: Default / Hover / Pressed / Disabled / LoadingIcon: True / FalseIcon Position: Left / Right
💡 Use Variants for visual states and Boolean for simple toggles.
5. Set Up Interactive States
Create a component set with these variants:
State = DefaultState = HoverState = PressedState = DisabledState = Loading
In Prototype mode:
- Add
While Hovering→ Hover - Add
On Click→ Pressed - Use
After Delay→ return to Default
✨ Result: A self-contained button that simulates real interaction.
6. Make It Responsive
Test the button at different label lengths:
- ✅ With short text: “OK”
- ✅ With long text: “Add to cart and checkout now”
- ✅ With/without icon
Ensure:
- Auto Layout doesn’t break
- Text wraps or clips correctly
- Spacing stays consistent
🧪 Add to a test frame and try resizing it horizontally.
7. Add Light and Dark Modes
Use Figma Variables with Mode = Light and Mode = Dark:
bg.button.primaryswitches values between themestext.button.labelswitches between black/white or opacity scales
🎨 Variables make theming seamless across brands or products.
8. Final Touch: Loading State
For loading:
- Replace label with spinner icon (or prefix it)
- Reduce opacity of button content (if not replacing)
- Disable pointer interactions (just for prototype clarity)
🌀 Use a loading Boolean property and combine with animation if needed.
9. Documentation and Dev Notes
Inside your component or library:
- Add a description with all props
- Note how tokens connect to code
- Explain sizing or responsive behavior
- Add links to GitHub/Storybook if used
🧾 Example:
yaml Props:
- size: sm, md, lg
- state: default, hover, pressed, disabled
- hasIcon: toggles icon instance slot
- mode: light/dark via token variable
Conclusion: Buttons Set the Tone
A well-built button does more than look good—it behaves, adapts, and communicates clearly. By connecting tokens, Auto Layout, variants, and interactions, your Figma button becomes a design system flagship: easy to use, easy to hand off, and hard to break.
Next up: “The Hidden Power of Boolean Properties in Figma Components” — learn how to simplify your design system logic with powerful yes/no toggles.
