Data views Required
Tell an empty start from an empty search
Show two different empty states. A new account with no records explains the feature and offers the first action. A search or filter with no matches names the filter and offers to clear it.
How to do it
Decide which empty state to show from whether any filter is active, not from the list alone. The first-use state has one line of help and one primary button, such as "Create your first invoice". The no-match state repeats the search words and offers a "Clear filters" button. Never show an empty table with headers only.
Example
function InvoicesEmpty({ filters, onClear }: { filters: InvoiceFilters; onClear: () => void }) {
if (hasActiveFilters(filters)) {
return <EmptyState title={`No invoices match "${filters.search}"`} action={<Button onClick={onClear}>Clear filters</Button>} />;
}
return <EmptyState title="No invoices yet" text="Send your first invoice in under a minute." action={<LinkButton href="/invoices/new" variant="primary">Create invoice</LinkButton>} />;
}
def invoices_empty_template(filters: InvoiceFilters) -> str:
if filters.is_active():
return "invoices/empty_no_matches.html"
return "invoices/empty_first_use.html"
How to check
Component tests render the view with no records and no filter, then with a filter and no matches. Each shows its own heading and button.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/data-views/empty-states.