Invoice List
Billing history. Amounts are right-aligned and tabular, which is the whole reason this is not a generic list — a money column that does not line up cannot be scanned.
src/components/ui/invoice-list.tsxAbout
From the component's own source, where it was written.
Billing history.
Amounts are right-aligned and tabular, which is the whole reason this is not a generic list: a column of money that does not line up at the decimal point cannot be scanned, and scanning is what a billing page is for.
Currency is per-invoice rather than per-list. An account that changed plan across a currency migration has both, and formatting the old ones with the new symbol would be wrong in a way nobody notices until an audit.
Install
npx astralyx-ui add invoice-list
Usage
import { InvoiceList } from '@/components/ui/invoice-list'
<InvoiceList invoices={invoices} onDownload={download} />Composer
Change the props and the source below follows.
- PaidUS$288.00
INV-2026-0009
· 12 seats
- PaidUS$264.00
INV-2026-0008
· 11 seats
- RefundedUS$264.00
INV-2026-0007
· Duplicate charge
- Past dueUS$240.00
INV-2026-0006
· 10 seats
<InvoiceList invoices={invoices} onDownload={download} />Examples
Billing history
<InvoiceList invoices={invoices} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
InvoiceList
Billing history.
Extends Omit<ComponentProps<'div'>, 'children'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| invoices | Invoice[] | required | { id, number, date, amount, currency?, status, description?, url? }. |
| onDownload | (invoice: Invoice) => void | — | A URL renders a real download link; otherwise the callback fires. |
| locale | string | 'en-GB' | — |
| emptyLabel | ReactNode | 'No invoices yet' | — |
Types
Invoice
| Field | Type | Description |
|---|---|---|
| id | string | — |
| number | string | — |
| date | Date | — |
| amount | number | — |
| currency? | string | Not per list: an account that changed plan across a currency migration has both, and formatting the old ones with the new symbol is wrong in a way nobody notices until an audit. |
| status | 'paid' | 'open' | 'past_due' | 'refunded' | 'void' | Labelled badge, never colour alone. |
| description? | ReactNode | — |
| url? | string | A URL renders a real download link; otherwise the callback fires. |