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:

CategoryWhat to Specify
PurposeWhat job the component does
AnatomyThe parts it is made of
VariantsSize, emphasis, density, icon options
StatesDefault, hover, focus, active, disabled, loading, error, success
BehaviorKeyboard, mouse, touch, and screen reader expectations
ConstraintsWhen not to use it

Essential Components to Master

ComponentWhat Good Looks Like
ButtonClear priority, visible states, compact label, safe disabled logic
InputLabel above, helper text, inline validation, autofill-friendly
Select/comboboxSearchable when option count is large, keyboard friendly
CardClear grouping without heavy chrome
Modal/dialogUsed sparingly, focus trapped, exit always obvious
ToastBrief, informative, non-blocking, optionally undo-capable
TabsGood for peers, not for deep hierarchies
TableScannable rows, sortable headers, useful states

State Coverage Table

StateWhy It Matters
DefaultBaseline behavior
HoverSignals interactivity on pointer devices
FocusEssential for keyboard users and accessibility
ActiveConfirms input in progress
DisabledPrevents invalid actions, but must explain why when needed
LoadingReduces uncertainty during async actions
SuccessReassures users the action worked
ErrorHelps users recover without panic
EmptyGuides users when no data exists

Button Rules

Strong button system

VariantUse
PrimaryBest next action on the screen
SecondaryValid but lower-priority action
TertiaryQuiet action, often inline
DestructiveDangerous action requiring clarity

Good button labels

  • Save changes
  • Invite teammate
  • Start free trial
  • Delete 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 TypeRecommended Response
First-time useExplain the value and the first step
Filtered emptyExplain why nothing matches and offer reset
No permissionsExplain access and next steps
Error stateExplain 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?