The state color problem no one plans for
Most color systems are designed around rest states. The design file has the default button, the primary accent, the surface colors — and the palette feels resolved. Then the first prototype ships and the team starts discovering: what does this button look like on hover? What changes on press? What about disabled? In the absence of a plan, these decisions get made ad hoc, by whoever is coding the component at the time. The result is usually inconsistent: some hover states are slightly lighter, some are slightly darker, some use opacity, and some add a border. A deliberate state color system defines these relationships once, before component work begins, and enforces them across the product.
The lightness-shift model for interactive states
The most predictable pattern for interactive state colors is a systematic lightness shift relative to the base. In a light-mode interface, the progression typically looks like this: default sits at the base hue, hover shifts 8-12% lighter, active shifts 6-10% darker than the default, and focus adds a high-contrast ring rather than changing the fill. On dark surfaces — the Nocturne Tech palette is a useful reference here — this reversal in direction is especially useful: hover states shift slightly toward the base surface color (slightly lighter), while active states deepen toward a near-black. The pattern works because it aligns with physical metaphor: hovering is approaching (lighter, less committed), pressing is sinking (darker, more committed).
Disabled state color: the accessibility edge case
Disabled colors are the most frequently under-specified state. The instinct is to make them gray — and that is mostly right — but the implementation matters. A disabled element should be clearly distinguishable from an enabled element (reduced contrast, desaturated fill) but not invisible. WCAG does not require disabled elements to meet 4.5:1 contrast ratio, but elements that are too low-contrast will be missed by users, creating confusion about whether the option is gone or just unavailable. The Dark Mode UI Kit includes pre-specified disabled-state tokens for each component type, which eliminates the guesswork and ensures the UI communicates clearly even in edge states.