In a typical fileDrawn, and usually the frame everything else is judged against.
What we doTaken from the file as the reference for spacing, fonts and colour tokens.
In a typical fileUsually drawn, sometimes only as a colour swap in a comment.
What we doBuilt, and switched off on touch screens. A hover effect that sticks on a phone looks like a bug.
Missing
In a typical fileAlmost never drawn. Frequently removed later because it “looks like an outline”.
What we doAlways visible, with enough contrast against the component and the page behind it. This is the one state we won't remove on request without explaining why.
Missing
In a typical fileRarely drawn. Assumed to be “the hover state, but more”.
What we doBased on the hover style, so the component feels like one object rather than three.
Missing
In a typical fileOccasionally drawn, usually as reduced opacity.
What we doFading alone fails contrast, so we use a set style for disabled controls. We also ask what the user should do instead. A disabled button with no explanation is a dead end.
Missing
In a typical fileNot in the file. Discovered during integration, decided in an afternoon.
What we doDecided up front. Does the button keep its width? Does the label stay? Does a screen reader announce the wait?
Missing
In a typical fileSometimes a red border in one frame, without the message.
What we doWe decide the message, where it appears, and whether the field keeps what was typed. That last choice decides whether the user fixes one detail or retypes the whole form.
Missing
In a typical fileDesigned with realistic content, so the empty case never appears.
What we doDefined for every list, table and search result. The empty state is the first thing a new user sees and the last thing anyone designs.
You get every state above on one page, at each screen size the design sets. It is quicker to review than a test site. It also ends the “that is not what I drew” argument. If a state is wrong, you see it in one place, not three screens deep in a journey.