A button in a mockup usually shows one state: the default. In the real product the same button is hovered, focused with a keyboard, pressed, disabled while a form is incomplete, and loading while a request is sent. Each of those is a UI state, and each one needs a design.
It helps to separate two groups. Interaction states come from the user: hover, focus, pressed and disabled. Data states come from the system: loading, empty, partial data, error and success. A list screen, for example, needs a design for when it is loading, when it has no items, when it has one item, when it has hundreds and when the request fails.
Focus states deserve special attention. People who use a keyboard or switch device depend on a visible focus indicator to know where they are. Removing the browser focus outline without a replacement is one of the most common accessibility failures.
The change between states is part of the design too. A short, clear transition from default to pressed confirms the tap. A loading state that turns smoothly into success tells people their action worked. Abrupt jumps, or animation that is too slow, make the interface feel unreliable.
A practical way to avoid missing states is to list them for each component before designing, or to model the component as a state machine: a set of states and the events that move between them. ExodeUI, which we make, works this way. You design each state and the transitions between them in one file, and your code sends the events that switch states in the real app.