Loading, empty, and failed are different promises to the user
An empty table looks like a simple component state. In a real data flow, it can hide several very different situations. The first request may still be running. A search may have completed with no matches. A refresh may
An empty table looks like a simple component state. In a real data flow, it can hide several very different situations.
The first request may still be running. A search may have completed with no matches. A refresh may have failed after an earlier successful load. The user may no longer have access to the data.
If all of them show βNo results,β the interface asks users to guess what happened and which action will help.
Give the message a state to describe
I would start with the product's states before designing the illustration or button:
| State | What the interface should communicate |
|---|---|
| Initial load | Results are not known yet |
| Successful empty result | This query returned no matches |
| Failed initial request | Results could not be retrieved |
| Refresh with existing data | Earlier results remain while a newer request runs |
| Failed refresh | Earlier results remain, but the update did not succeed |
| Unavailable data | The current access or availability boundary |
This is an illustrative model, not a requirement to create six components. Its purpose is to stop different facts from sharing an inaccurate message.
Empty should explain the current query
A successful empty result can support useful actions: clear filters, widen the search, or create a first record where that makes sense.
The message should match the scope. βNo listings match these filtersβ is different from βThere are no listings.β
For dependent filters, also check that the displayed controls reflect the actual query. A hidden incompatible value can produce an empty result the user cannot explain from the screen.
Decide what to do with previous data
During refresh, keeping the last successful result can reduce disruption. It needs an honest presentation of freshness and a rule for actions that require current data.
For example:
Showing results fetched at 10:42.
The latest refresh failed. Retry.
Even that timestamp needs a definition. Fetch time, server generation time, and source observation time can describe different moments. Choose the one the UI needs, and label it accordingly.
A read-only overview and an approval action may need different policies. The overview can remain useful with older data; the approval may require a fresh server-side check before changing the record.
Recovery should fit the failure
A Retry button helps with some failures. It is less helpful when a filter is invalid or the user's access has changed.
I would map the recovery action to the known problem and preserve useful input. If the user spent time configuring a query, a failed request should not automatically wipe it out.
For unavailable private data, the message also needs an appropriate disclosure boundary. Explain what the user can do without revealing records they are not allowed to see.
Communicate changes without unnecessary focus movement
When a result or status changes while focus stays elsewhere, the relevant update may need an accessible announcement. W3C's status-message guidance describes how status can be exposed to assistive technology without taking focus.
A concise status can help. Announcing every intermediate change can create noise. Test the actual interaction instead of treating an attribute as proof that the experience works.
Test transitions as well as screenshots
I would check a slow first load, a successful zero-match search, a failed refresh after a successful result, and a change in access while the page is open.
For each transition, inspect three things together: the message, the data still visible, and the actions still available.
The empty-state design is successful when those three tell the same story. The visual treatment can then make that story easier to understand.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.