KQ-680 · INVOICE/BUILD

Invoice Build

An invoice that does its own arithmetic in front of you: a new line opens from zero to a ResizeObserver-measured height on glide while its content slides in from 16px, and the subtotal, tax and total roll their digit columns to the new figures on snap. Removing a line closes the same measured height on the exit ease, which accelerates away rather than springing back, and the figures roll down as it goes. Every remove is a real button carrying its line's description, and removing the row you are standing on hands focus to the next one, so a keyboard run of deletions never dumps focus on the body.

KQ-680 · INVOICE/BUILD
Invoice FW-22143 lines
  • Rig hire, 3 at $120.00, $360.00
  • Site survey, 1 at $480.00, $480.00
  • Cable spool, 12 at $18.50, $222.00
Subtotal
Subtotal $1,062.00
Tax 8%
Tax 8 percent, $84.96
Total
Total $1,146.96

Fernworks Fabrication · net 14 days

Total $1,146.96 across 3 lines

Lines 3 · total $0.00

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/invoice-build

Props

lines
InvoiceLine[]
default
The lines: id, description, qty and unitPrice. Adding one slides it in; removing one collapses it.
onRemove
(id: string) => void
default
Fires from the press on a line's remove button; drop the line to play the collapse.
taxRate
number
default 0.08
Fraction of the subtotal charged as tax; the rate is printed as a percentage in the tax label.
format
(value: number) => string
default Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
Turns an amount into its printed string. The default pins an explicit locale so server and client agree.
onTotalChange
(total: number, subtotal: number, tax: number) => void
default
Fires from the effect that observes a settled change of the three figures.
label
string
default "Invoice"
Names the line list and the totals for assistive technology.
note
React.ReactNode
default
A quiet caption under the totals — the account or the terms.
emptyLabel
string
default "No lines yet."
The designed empty state; no height is reserved for it.