Skip to content
All Taste components

Data display

Empty state

What a list shows before it has anything in it, with the one action that fills it.

icon · title · help text · primary and secondary action

No invoices yet

Create your first invoice, or bring in the ones you already have from a spreadsheet.

import { FileText, Plus, Upload } from "lucide-react";

export function EmptyState({ onCreate, onImport }: { onCreate: () => void; onImport: () => void }) {
  return (
    <div className="grid w-full max-w-[440px] justify-items-center gap-1 rounded-lg border border-dashed border-border-strong px-6 py-10 text-center">
      <span className="relative mb-3 grid size-12 place-items-center rounded-lg bg-surface-2 text-fg-muted">
        <FileText className="size-[22px]" aria-hidden />
        <span className="absolute -bottom-1.5 -right-1.5 grid size-5 place-items-center rounded-full bg-primary text-primary-fg ring-[3px] ring-bg">
          <Plus className="size-3" aria-hidden />
        </span>
      </span>
      <h3 className="text-[15px] font-semibold tracking-tight">No invoices yet</h3>
      <p className="mb-4 max-w-[300px] text-[13.5px] text-fg-muted">
        Create your first invoice, or bring in the ones you already have from a spreadsheet.
      </p>
      <div className="flex flex-wrap justify-center gap-2">
        <button type="button" onClick={onCreate}
          className="inline-flex h-9 items-center gap-1.5 rounded bg-primary px-3.5 text-sm font-medium text-primary-fg hover:bg-primary-hover">
          <Plus className="size-4" aria-hidden />New invoice
        </button>
        <button type="button" onClick={onImport}
          className="inline-flex h-9 items-center gap-1.5 rounded border border-border-strong bg-bg px-3.5 text-sm font-medium text-fg hover:bg-surface">
          <Upload className="size-4" aria-hidden />Import CSV
        </button>
      </div>
    </div>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.