Components and States
Users experience your product through components, not design files. Great UI requires components that are reusable, predictable, and fully specified.
The Minimum Component Contract
Every component should define:
| Category | What to Specify |
|---|---|
| Purpose | What job the component does |
| Anatomy | The parts it is made of |
| Variants | Size, emphasis, density, icon options |
| States | Default, hover, focus, active, disabled, loading, error, success |
| Behavior | Keyboard, mouse, touch, and screen reader expectations |
| Constraints | When not to use it |
Essential Components to Master
| Component | What Good Looks Like |
|---|---|
| Button | Clear priority, visible states, compact label, safe disabled logic |
| Input | Label above, helper text, inline validation, autofill-friendly |
| Select/combobox | Searchable when option count is large, keyboard friendly |
| Card | Clear grouping without heavy chrome |
| Modal/dialog | Used sparingly, focus trapped, exit always obvious |
| Toast | Brief, informative, non-blocking, optionally undo-capable |
| Tabs | Good for peers, not for deep hierarchies |
| Table | Scannable rows, sortable headers, useful states |
State Coverage Table
| State | Why It Matters |
|---|---|
| Default | Baseline behavior |
| Hover | Signals interactivity on pointer devices |
| Focus | Essential for keyboard users and accessibility |
| Active | Confirms input in progress |
| Disabled | Prevents invalid actions, but must explain why when needed |
| Loading | Reduces uncertainty during async actions |
| Success | Reassures users the action worked |
| Error | Helps users recover without panic |
| Empty | Guides users when no data exists |
Button Rules
Strong button system
| Variant | Use |
|---|---|
| Primary | Best next action on the screen |
| Secondary | Valid but lower-priority action |
| Tertiary | Quiet action, often inline |
| Destructive | Dangerous action requiring clarity |
Good button labels
Save changesInvite teammateStart free trialDelete project
Avoid vague labels like Submit, Continue, or OK when a more specific verb is possible.
Button example
<button class="btn btn-primary">Start free trial</button>
<button class="btn btn-secondary">View demo</button>
<button class="btn btn-danger">Delete workspace</button>
.btn {
min-height: 44px;
padding: 0 16px;
border-radius: 10px;
font-weight: 600;
}
.btn:focus-visible {
outline: 3px solid rgba(91, 140, 255, 0.45);
outline-offset: 2px;
}
Input Rules
- Labels above inputs for fast scanning
- Placeholder as hint, not as the only label
- Helper text before errors happen when requirements are non-obvious
- Inline validation after user interaction, not immediately on first keystroke
- Preserve entered values on error
Dialog Rules
Use a modal when the user must make a focused decision before continuing.
Do not use a modal for:
- long forms
- information users may want to compare against the page beneath
- flows that deserve a full page with URL and history
If a user may need to compare information, copy text, or step through multiple stages, prefer a full page or side panel.
Empty States Are Product Design
| Empty State Type | Recommended Response |
|---|---|
| First-time use | Explain the value and the first step |
| Filtered empty | Explain why nothing matches and offer reset |
| No permissions | Explain access and next steps |
| Error state | Explain problem, provide retry or support path |
Common Mistakes
- shipping only the happy path component state
- making disabled buttons the only explanation of what is wrong
- using toast messages for critical failures that users can miss
- building separate one-off components instead of extending the system
Quality Check
Before a component ships, ask:
- Does it work with mouse, keyboard, touch, and screen readers?
- Are all states visually and behaviorally defined?
- Is the label specific?
- Does it match the rest of the system?
- Is there a simpler existing pattern we should use instead?