Button Design
Don't settle for browser defaults.
Complete Lifecycle: A well-designed button handles idle, hover, press, loading, and success states seamlessly.
The Essential States
Idle State
The default resting state. Clearly clickable with hover effects.
Hover State
Provides feedback when cursor is over the button. Signals interactivity.
Focus State
Shows keyboard focus with a visible ring. Essential for accessibility.
Pressing State
Visual feedback on press. Scale-down or click effect.
Pending State
Shows progress while waiting. Prevents double-clicks.
Disabled State
Indicates unavailable action. Reduced opacity and no pointer.
Disabled State UX
Visual Feedback: When a button is disabled, the cursor should immediately change to indicate the action is forbidden.
Button States Implementation
Click on each state to see which parts of the code handle it. A complete button should handle all five states in a single, unified component.
Idle: The default resting state. Clearly clickable with base styling.
💡 Tip: Base styles define the button's default appearance. Keep these consistent across your design system.
Button Variants
Buttons with icons require special attention to optical alignment. When adding icons, the padding should be adjusted to maintain visual balance.
Visual Hierarchy
Primary (Filled)
When to use: Main call-to-action that demands immediate attention. Use Brand for the primary CTA (one per screen/section) and Neutral for important but non-primary actions like "Cancel" or "Back".
Secondary (Tinted)
When to use: Actions that need emphasis without competing with primary CTAs. Great for card actions, toolbar buttons, or when you have multiple actions of similar importance. The tinted background provides visual weight without overwhelming.
Tertiary (Minimal)
When to use: Low-priority actions that shouldn't distract from main content. Ideal for "Skip", "Learn more", "Dismiss", or repeated/inline actions. They stay invisible until hovered, keeping the UI clean.
Quick Reference
Primary (Filled)
- • Main CTA per section
- • "Submit", "Confirm", "Save"
- • High visual prominence
Secondary (Tinted)
- • Supporting actions
- • Card/toolbar buttons
- • Medium visual weight
Tertiary (Minimal)
- • Low-priority actions
- • "Skip", "Dismiss", links
- • Minimal visual weight
Destructive Actions
Variant States
With Leading Icon
Try hovering and clicking!
When to Use Leading Icons
Back/Return actions
The arrow naturally points to where you're going.
Confirmation actions
Check marks before "Approve", "Confirm", "Accept".
Add/Create actions
Plus icon before "Add Item", "New Project".
Feature emphasis
Drawing attention to the action type first.
With Trailing Icon
Notice how the reduced right padding (pr-4) keeps the content visually centered.
When to Use Trailing Icons
Forward/Next actions
"Continue", "Next Step", "Proceed".
External links
Indicating the action opens something new.
Dropdown triggers
Chevron indicating expandable content.
Download actions
Arrow pointing down after "Download".
Rule of thumb: Trailing icons often indicate direction or consequence of the action.
Icon Only
Icon-only buttons work great for toolbars and compact UIs.
When to Use Icon-Only Buttons
Toolbars & action bars
Where space is limited and icons are universally understood.
Repeated actions
Close buttons, expand/collapse, media controls.
Mobile interfaces
Maximizing touch target while saving horizontal space.
Universally recognized icons
Play, pause, close, settings, search.
👁️ Why Optical Alignment Matters
Icons are visually denser than whitespace. When you place an icon at the edge of a button, it creates an optical illusion where that side appears "heavier" than the other.
By reducing the padding on the icon side, you're compensating for this visual weight, making the button appear evenly balanced. This is the same principle used in typography when kerning letters—mathematical spacing isn't always visually correct.
Best Practices
Keep transitions snappy
Use 100-200ms for state changes. Any longer feels sluggish.
Prevent double-clicks
Always disable the button during loading to prevent duplicate submissions.
Update button text
Change from 'Submit' to 'Processing...' to 'Done!' for clear communication.
Show success state
After completing an action, briefly show a success state before resetting.
Maintain contrast
Even in disabled state, ensure text remains readable for accessibility.
Why Button States Matter
- 🧠Reduces uncertainty — Users know their action was registered
- 🚫Prevents errors — Loading state blocks double-submissions
- ✨Feels premium — Polished micro-interactions build trust
- ♿Improves accessibility — Clear states help all users understand what's happening