Files
zeekay 05fc512820 feat: sync upstream shadcn/ui — [email protected], v4 app, font system, chart improvements
Upstream sync from shadcn-ui/ui (1686 commits since last merge base).

Key changes:
- packages/shadcn upgraded to 4.1.0 (CLI font transformers, scaffold from github, chart colors)
- apps/v4 replaces apps/www as the primary docs/registry app
- Font system: 25+ heading font registries, font markers utility, @supports override
- Chart improvements: recharts v3 compat, radial chart fixes
- templates/ updated with monorepo variants (astro, vite, react-router, start)
- skills/shadcn AI skill definitions added
- deprecated/ removed (auth, auth-firebase, cli, www)

Preserved Hanzo-only paths: app/, pkg/, demo/, docs/, template/next/
2026-03-24 19:04:31 -07:00

116 lines
3.2 KiB
TypeScript

"use client"
import { Badge } from "@/registry/bases/base/ui/badge"
import { Button } from "@/registry/bases/base/ui/button"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/registry/bases/base/ui/card"
import {
Table,
TableBody,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@/registry/bases/base/ui/table"
const INVOICE_ITEMS = [
{ item: "Design System License", qty: 1, unitPrice: 499 },
{ item: "Priority Support", qty: 12, unitPrice: 99 },
{ item: "Custom Components", qty: 3, unitPrice: 250 },
] as const
const subtotal = INVOICE_ITEMS.reduce(
(sum, row) => sum + row.qty * row.unitPrice,
0
)
const tax = 0
const totalDue = subtotal + tax
function formatCurrency(value: number) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 2,
}).format(value)
}
export function Invoice() {
return (
<Card>
<CardHeader>
<CardTitle>Invoice #INV-2847</CardTitle>
<CardDescription>Due March 30, 2026</CardDescription>
<CardAction>
<Badge variant="secondary">Pending</Badge>
</CardAction>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Item</TableHead>
<TableHead className="text-right">Qty</TableHead>
<TableHead className="text-right">Rate</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{INVOICE_ITEMS.map((row) => (
<TableRow key={row.item}>
<TableCell>{row.item}</TableCell>
<TableCell className="text-right tabular-nums">
{row.qty}
</TableCell>
<TableCell className="text-right tabular-nums">
{formatCurrency(row.unitPrice)}
</TableCell>
<TableCell className="text-right tabular-nums">
{formatCurrency(row.qty * row.unitPrice)}
</TableCell>
</TableRow>
))}
<TableRow>
<TableCell colSpan={3} className="text-right">
Subtotal
</TableCell>
<TableCell className="text-right tabular-nums">
{formatCurrency(subtotal)}
</TableCell>
</TableRow>
<TableRow>
<TableCell colSpan={3} className="text-right">
Tax
</TableCell>
<TableCell className="text-right tabular-nums">$0.00</TableCell>
</TableRow>
<TableRow>
<TableCell colSpan={3} className="text-right">
Total Due
</TableCell>
<TableCell className="text-right tabular-nums">
{formatCurrency(totalDue)}
</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
<CardFooter>
<Button variant="outline" size="sm">
Download PDF
</Button>
<Button size="sm" className="ml-auto">
Pay Now
</Button>
</CardFooter>
</Card>
)
}