Derive hover, active, and disabled states from your scale
A worked tutorial: stop eyeballing interactive states — derive hover, active, focus, and disabled directly from scale steps with rules that hold.
The one-step rule for hover and active
The most reliable system in UI color: hover is one scale step darker than rest (one step lighter in dark mode), active is two steps. If your primary button rests at 600, hover is 700, active is 800. No eyeballing, no per-button snowflakes — the rule works because perceptual scales make each step feel equal.
Apply it uniformly: links, menu items, table rows, chips. Users learn the physics of your interface from repetition; five different hover behaviors teach them nothing.
Focus and disabled need their own logic
Focus is not a darker state — it is an added ring. Use a 2px outline in the action hue at full saturation plus a 2px offset, and never remove it for aesthetics; keyboard users navigate by it. Check the ring against adjacent colors at 3:1, the UI-component threshold.
Disabled is reduced opacity on the resting state (around 50%) with no hover response at all — and crucially, disabled must never be the only signal. Pair it with helper text explaining why, because grayed controls test users' patience more than their eyes.
Verify states like a user, not a designer
Tab through the interface with the monitor dimmed: every focus ring must be findable, every hover distinguishable from rest, every disabled control obviously inert. Then measure the text pairs in each state — hover darkens backgrounds, which usually helps contrast, but light-mode-to-dark hover inversions can break it.
Document the rules as tokens (action-hover, action-active, focus-ring) rather than values. When the brand hue changes next year, the physics survive.
Tip
Record a 10-second clip of tabbing through the form and watch it back. State problems you glide past live become obvious on replay.
Related free tools
Want to apply this right now? Open the color palette generator and try it with your own brand color — free, no sign-up.