Skip to content
kerfjsGitHub

Invoices

Past invoices, with a pinned banner if a payment failed.

SourcePackage @kerf-js/veneer

Preview

tsx
import { Invoices } from '@kerf-js/veneer'import type { Invoice } from '@kerf-js/veneer'export function History() {  return (  <Invoices    invoices={BILLS}    onExport={() => {}}  />  )}const BILLS: Invoice[] = [  {    id: '10',    date: 'Oct 1',    number: 'INV-2026-10',    status: 'paid',    amount: 8560,    pdf: '/samples/invoice.pdf',  },  {    id: '09',    date: 'Sep 1',    number: 'INV-2026-09',    status: 'paid',    amount: 8230,    pdf: '/samples/invoice.pdf',  },  {    id: '08',    date: 'Aug 1',    number: 'INV-2026-08',    status: 'paid',    amount: 8010,    pdf: '/samples/invoice.pdf',  },  {    id: '07',    date: 'Jul 1',    number: 'INV-2026-07',    status: 'paid',    amount: 7620,    pdf: '/samples/invoice.pdf',  },  {    id: '06',    date: 'Jun 1',    number: 'INV-2026-06',    status: 'paid',    amount: 7690,    pdf: '/samples/invoice.pdf',  },  {    id: '05',    date: 'May 1',    number: 'INV-2026-05',    status: 'paid',    amount: 7380,    pdf: '/samples/invoice.pdf',  },  {    id: '04',    date: 'Apr 1',    number: 'INV-2026-04',    status: 'paid',    amount: 7240,    pdf: '/samples/invoice.pdf',  },  {    id: '03',    date: 'Mar 1',    number: 'INV-2026-03',    status: 'paid',    amount: 6710,    pdf: '/samples/invoice.pdf',  },]

Installation

npm install @kerf-js/veneer

Usage

tsx
import { Invoices } from '@kerf-js/veneer'<Invoices  invoices={BILLS}  onExport={() => {}}/>

A failed payment

Press Update payment method to clear it here.

tsx
import { state } from '@kerf-js/core'import { Invoices } from '@kerf-js/veneer'import type { Invoice } from '@kerf-js/veneer'export function Failed() {  const fixed = state(false)  return (    <Invoices      invoices={fixed.value ? BILLS : OVERDUE_BILLS}      onUpdatePayment={() => (fixed.value = true)}    />  )}const BILLS: Invoice[] = [  {    id: '10',    date: 'Oct 1',    number: 'INV-2026-10',    status: 'paid',    amount: 8560,    pdf: '/samples/invoice.pdf',  },  {    id: '09',    date: 'Sep 1',    number: 'INV-2026-09',    status: 'paid',    amount: 8230,    pdf: '/samples/invoice.pdf',  },  {    id: '08',    date: 'Aug 1',    number: 'INV-2026-08',    status: 'paid',    amount: 8010,    pdf: '/samples/invoice.pdf',  },  {    id: '07',    date: 'Jul 1',    number: 'INV-2026-07',    status: 'paid',    amount: 7620,    pdf: '/samples/invoice.pdf',  },  {    id: '06',    date: 'Jun 1',    number: 'INV-2026-06',    status: 'paid',    amount: 7690,    pdf: '/samples/invoice.pdf',  },  {    id: '05',    date: 'May 1',    number: 'INV-2026-05',    status: 'paid',    amount: 7380,    pdf: '/samples/invoice.pdf',  },  {    id: '04',    date: 'Apr 1',    number: 'INV-2026-04',    status: 'paid',    amount: 7240,    pdf: '/samples/invoice.pdf',  },  {    id: '03',    date: 'Mar 1',    number: 'INV-2026-03',    status: 'paid',    amount: 6710,    pdf: '/samples/invoice.pdf',  },]const OVERDUE_BILLS: Invoice[] = [  {    id: '11',    date: 'Nov 1',    number: 'INV-2026-11',    status: 'failed',    amount: 8930,  },  {    id: '10r',    date: 'Oct 1',    number: 'INV-2026-10',    status: 'retrying',    amount: 8560,  },  ...BILLS.slice(1, 4),]

Accessibility

  • This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and veneer's parts keep their roles and labels.

API Reference

PropTypeDefaultDescription
invoicesreadonly Invoice[] | State<readonly Invoice[]>—The rows.
currencystring—A currency code.
localestring—The locale for the amounts.
EventTypeDefaultDescription
onUpdatePayment(() => void)—The banner's button.
onExport(() => void)—Shows Export CSV.

RelatedPayment methodsUsage meter