Klarhimmel UI

App, invoice list

App, invoice list preview

Install

npx shadcn add @klarhimmel/app-billing-invoices

Usage

import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppBillingInvoices from '@/components/klarhimmel/blocks/app-billing-invoices';

export default function Section() {
  return (
    <Theme theme="brand">
      <BlockSurface>
        <AppBillingInvoices props={{
          "eyebrow": "Billing",
          "title": "Invoices",
          "description": "Every invoice for Exempelhotellet. Download one as a PDF.",
          "caption": "Invoices, newest first",
          "columns": {
            "number": "Invoice",
            "date": "Date",
            "amount": "Amount",
            "status": "Status"
          },
          "rows": [
            {
              "number": "INV-1042",
              "date": "1 Jun 2026",
              "amount": "490 kr",
              "status": "due",
              "href": "#inv-1042"
            },
            {
              "number": "INV-1031",
              "date": "1 May 2026",
              "amount": "490 kr",
              "status": "paid",
              "href": "#inv-1031"
            },
            {
              "number": "INV-1019",
              "date": "1 Apr 2026",
              "amount": "490 kr",
              "status": "paid",
              "href": "#inv-1019"
            },
            {
              "number": "INV-1007",
              "date": "1 Mar 2026",
              "amount": "490 kr",
              "status": "failed",
              "href": "#inv-1007"
            }
          ],
          "statusLabels": {
            "paid": "Paid",
            "due": "Due",
            "failed": "Failed"
          },
          "download": "Download PDF",
          "scrollHint": "Scroll sideways for more columns",
          "recovery": {
            "payAgain": "Pay again",
            "updateCard": {
              "label": "Update card",
              "href": "#card"
            },
            "processing": "Processing",
            "said": "Payment attempt started. We will email you the result."
          },
          "state": "filled",
          "messages": {
            "emptyTitle": "No invoices yet",
            "emptyBody": "Your first invoice appears here at the end of the first billing month."
          }
        }} />
      </BlockSurface>
    </Theme>
  );
}

Install

Import

import Block from '@/components/klarhimmel/blocks/app-billing-invoices';
Also called
  • app/billing-invoices
About
A list of invoices as a table: number, date, amount, a status badge (paid, due, failed: always a word) and a download link named for its invoice that stays in view while the other columns scroll, and a failed invoice that can be paid…
Category
Interface sections for signed-in products.

Notes

When to use it

A table of past invoices with status and a download link per row, for a billing page. For the current plan and usage use `app-billing-plan`; for a generic table of other data use `app-data-table`.

Writing for it

- Rows take 1 to 8 entries. Each has a number, date and amount of 30 characters at most, a status of paid, due or failed, and an `href` for the download file. - Set `download` (30) to a short verb like Download; the invoice number is appended for screen readers so the link is not just the same word eight times. - Use `recovery` only for failed rows: `payAgain` and an `updateCard` link appear there, and `said` (80) is the announcement after a retry.

Watch out for

Eight rows is the ceiling, so a long history needs `app-data-pagination` or a link elsewhere. In the empty state `messages.emptyTitle` is required, and the Pay again button only changes the row to processing locally; it does not charge anything.

Usage

The block in a page, with its default content (long lists shortened). Every prop is in the table below.

section.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { BlockSurface } from '@/components/klarhimmel/blocks/surface';
import AppBillingInvoices from '@/components/klarhimmel/blocks/app-billing-invoices';

export default function Section() {
  return (
    <Theme theme="brand">
      <BlockSurface>
        <AppBillingInvoices props={{
          "eyebrow": "Billing",
          "title": "Invoices",
          "description": "Every invoice for Exempelhotellet. Download one as a PDF.",
          "caption": "Invoices, newest first",
          "columns": {
            "number": "Invoice",
            "date": "Date",
            "amount": "Amount",
            "status": "Status"
          },
          "rows": [
            {
              "number": "INV-1042",
              "date": "1 Jun 2026",
              "amount": "490 kr",
              "status": "due",
              "href": "#inv-1042"
            }
          ],
          "statusLabels": {
            "paid": "Paid",
            "due": "Due",
            "failed": "Failed"
          },
          "download": "Download PDF",
          "scrollHint": "Scroll sideways for more columns",
          "recovery": {
            "payAgain": "Pay again",
            "updateCard": {
              "label": "Update card",
              "href": "#card"
            },
            "processing": "Processing",
            "said": "Payment attempt started. We will email you the result."
          },
          "state": "filled",
          "messages": {
            "emptyTitle": "No invoices yet",
            "emptyBody": "Your first invoice appears here at the end of the first billing month."
          }
        }} />
      </BlockSurface>
    </Theme>
  );
}

Props

The type, default and text limit of every prop. On a real page, over-limit text is kept and checkSections flags it (Installation, Check a page before you ship); this live preview shows the default until it fits. The panel above edits all props.

PropTypeDefaultDescription
eyebrowstring'Billing'Text, up to 60 characters. Optional; empty is not rendered.
titlestring'Invoices'Text, up to 120 characters.
descriptionstring'Every invoice for Exempelhotellet. …'Text, up to 300 characters. Optional; empty is not rendered.
captionstring'Invoices, newest first'Text, up to 80 characters.
columns{ number, date, amount, status }{…}Fields: number, date, amount, status.
rows{ number, date, amount, status, href }[]4 itemsList of 1 to 8. Each item: number, date, amount, status ('paid' | 'due' | 'failed'), href.
statusLabels{ paid, due, failed }{…}Fields: paid, due, failed.
downloadstring'Download PDF'Text, up to 30 characters.
scrollHintstring'Scroll sideways for more columns'Text, up to 40 characters.
recovery{ payAgain, updateCard, processing, said }{…}Fields: payAgain, updateCard, processing, said.
state'filled' | 'empty''filled'One of 'filled', 'empty'.
messages{ emptyTitle, emptyBody }{…}Fields: emptyTitle, emptyBody.
headingLevel'1' | '2'-One of '1', '2'. Optional; empty is not rendered.