Data states
Every data view must handle five states, not just the happy path: loading, populated, empty, error, and partial/stale. A skeleton should resemble the final layout; empty offers one next step; error names the failure and offers retry; partial data is labelled rather than shown as current.
| Status | |
|---|---|
| Ada Okafor | active |
| Bruno Sato | invited |
The five states
- Loading — skeleton rows that match the real column layout, not a spinner in the middle of the page.
- Populated — the data, with overflow, long names and 0/1/n handled.
- Empty — first-run gets one create action; a filtered-out list gets a way back, not “create”.
- Error — name the failed operation and offer retry; distinct from inline field validation.
- Partial / stale — keep the last good data visible during a refresh and label it, rather than blanking the view.
Composed with the table
EmptyState and ErrorState drop straight into the DataTable empty and error slots, so the table's lifecycle uses the same state vocabulary as the rest of the app.
<DataTable data={rows} columns={columns} isLoading={isLoading} empty={<EmptyState title="No members yet" action={<Button>Invite member</Button>} />} error={error ? <ErrorState title="Couldn't load members" onRetry={refetch} /> : undefined}/>