𝗗𝗼𝗻'𝘁 𝗨𝘀𝗲 𝗢𝗻𝗲 𝗚𝗲𝗻𝗲𝗿𝗶𝗰 𝗘𝗺𝗽𝘁𝘆 𝗦𝘁𝗮𝘁𝗲 𝗙𝗼𝗿 𝗬𝗼𝘂𝗿 𝗗𝗮𝘁𝗮 𝗧𝗮𝗯𝗹𝗲𝘀
Most data tables ship with one single message: "No data."
It looks fine in a design review. It creates support tickets in production.
An empty table means three different things. Each case needs a specific design, specific text, and a specific action.
Here are the three cases you must design separately:
First-use (No data exists yet) The user is new. They want to know what this table does and how to start. • The goal: Onboard the user. • The text: Explain the purpose of the table. • The action: Provide a button to create the first item or import data. • Avoid: A dead-end message like "No data."
Filtered-empty (Data exists but filters hide it) The user applied filters that return zero results. They often think the tool is broken. • The goal: Help the user find their data. • The text: Explicitly state which filters are active. • The action: Provide a button to clear all filters or edit them. • Avoid: A generic message that ignores the active filters.
Load-failure (The request failed) The server returned an error or the network went down. • The goal: Help the user recover. • The text: Explain that the load failed and show a timestamp or error code. • The action: Provide a retry button. • Avoid: Telling the user "No data" when the problem is actually a technical error.
Why teams fail at this:
- They design empty states too late in the process.
- They only test with demo data, so they never see the empty state.
- They treat empty states as edge cases.
In reality, empty states are high-leverage moments. A good empty state moves a user from zero to value in minutes. A bad one leaves them confused and frustrated.
Build your table component to handle these conditions separately. It costs little to design them now, but it saves huge amounts of support time later.