Transactions grouped by day under sticky headers, each with its net total.
import { TransactionLedger } from "@/components/eased/transaction-ledger/transaction-ledger";import { useLiveTimeline } from "@/components/eased/_primitives/timeline-core/timeline-core";const feed = useLiveTimeline(transactions);<TransactionLedger transactions={feed.events} entering={feed.entering} now={Date.now()} categories={categories} onCategoryChange={recategorise} />Installation
npx shadcn add @eased-pro/transaction-ledgerNeeds the @eased-pro registry and your Pro token in components.json. Create a token and copy the setup from your account .
Props
| Prop | Type | Default | |
|---|---|---|---|
transactions | TimelineEvent<LedgerTxn>[] | timeline-core events; data is { amount, currency, category, merchant, status } (negative is money out). | |
now | number | "Today" / "Yesterday" are relative to it. | |
categories | string[] | Offered in each row's menu. | |
onCategoryChange | (id, category) => void | ||
filter | "all" | "in" | "out" | "all" | |
entering | (id) => number | null | From useLiveTimeline; new rows rise once. | |
baseCurrency | string | "USD" | Currency of each day's net. |
locale / timeZone | string | runtime |
Put it in a scroll region; headers stick to its top. Rows share one grid, so amounts and statuses keep one right edge.
Motion signature: a pending row that settles washes once while its status swaps with a blur; a new row rises 6px at the top and nothing else moves; the category menu grows from its chip. Filters apply instantly (rule 84). Reduced motion: fades only.