KQ-2084 · BUDGET/POUR
Budget Pour
An agent asking to spend money, drawn against the budget it would come out of: the bar shows paid, promised and the room left, and the order sits above it as a block of its line items starting exactly where the room left starts. A cap handle at the block's end follows the pointer 1:1, rubber-bands and settles on the nearest $10 on springs.snap, and every item past it lets go of the block and strikes in the list. Approve runs one pour front across the block on springs.glide at pourSpeed: behind it the block drains down a sloped surface into a thin stream, the bar's fill grows under the stream and the room left counts down; over budget the block overhangs the bar in danger, above the second-approval line your approval waits for the second, and an expired quote holds the decision. The cap is a slider (arrows $10, Shift $100, Page keys $250, Home, End) and Enter on it approves.
Fieldline purchasing agent wants to spend $2,872.00
Soil sensors for the north plots · quote Q-3318 valid 3 more days
cap $2,872.00 · 6 of 6 items · $568.00 left after
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/budget-pour
Props
- request
- BudgetRequest
- default defaultBudgetRequest
- The spend asked for: { id, agent, title, reason, vendor, quote: { id, validUntil }, items, requestedAt }; items are in priority order and the cap trims from the bottom.
- budget
- BudgetPot
- default defaultBudgetPot
- The budget it comes out of: { id, name, total, spent, committed }.
- cap / defaultCap
- number
- default — / the request total
- Most the agent may spend on this order, controlled or initial.
- onSetCap
- (cap) => void
- default —
- Fires when a drag, key or Cap at what's left settles the cap.
- onApprove
- (amount, items) => void | Promise
- default —
- Your approval, with the amount and the items that fit under the cap; a promise holds the pour until it resolves and a rejection is stated.
- onReject
- (note) => void
- default —
- Declined, with the reviewer's optional note.
- onRequestQuote
- () => void
- default —
- Ask for a new quote was pressed on an expired quote.
- secondApprovalAbove
- number
- default 3000
- Orders above this need every approver, not only you.
- approvers
- BudgetApprover[]
- default you and Mara Ilves
- Who approves: { id, name, you? }; the one marked you is the viewer.
- approvals
- string[]
- default —
- Controlled ids of approvers who have approved; the held order pours when all have. Your own approval counts as soon as you give it.
- status
- "ready" | "loading" | "empty" | "error"
- default "ready"
- Whether the request has loaded.
- onRetry
- () => void
- default —
- Try again was pressed after a failure to load.
- now
- number
- default Oct 17 2026, 14:00 UTC
- The moment the quote's validity is counted from, in ms.
- barStyle
- "solid" | "cells" | "rail"
- default "solid"
- How the budget is drawn: a solid bar, $250 cells cut by a repeating mask, or a 4px rail with $1,000 ticks.
- pourSpeed
- number
- default 1
- How fast the approved amount pours, as a multiple of the glide's pace from 0.5 to 2; the damping ratio stays the glide's.
- accent
- "cobalt" | "plum" | "mint" | "ink" | string
- default "cobalt"
- The order, its pour and Approve: a named pigment or any CSS colour.
- formatMoney
- (amount) => string
- default Intl USD
- How money is written.
- height
- number
- default 560
- Tallest the surface grows, in px, before its body scrolls.
- disabled
- boolean
- default false
- Read only.
- className
- string
- default —
- Classes for the surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| request | BudgetRequest | defaultBudgetRequest | The spend asked for: { id, agent, title, reason, vendor, quote: { id, validUntil }, items, requestedAt }; items are in priority order and the cap trims from the bottom. |
| budget | BudgetPot | defaultBudgetPot | The budget it comes out of: { id, name, total, spent, committed }. |
| cap / defaultCap | number | — / the request total | Most the agent may spend on this order, controlled or initial. |
| onSetCap | (cap) => void | — | Fires when a drag, key or Cap at what's left settles the cap. |
| onApprove | (amount, items) => void | Promise | — | Your approval, with the amount and the items that fit under the cap; a promise holds the pour until it resolves and a rejection is stated. |
| onReject | (note) => void | — | Declined, with the reviewer's optional note. |
| onRequestQuote | () => void | — | Ask for a new quote was pressed on an expired quote. |
| secondApprovalAbove | number | 3000 | Orders above this need every approver, not only you. |
| approvers | BudgetApprover[] | you and Mara Ilves | Who approves: { id, name, you? }; the one marked you is the viewer. |
| approvals | string[] | — | Controlled ids of approvers who have approved; the held order pours when all have. Your own approval counts as soon as you give it. |
| status | "ready" | "loading" | "empty" | "error" | "ready" | Whether the request has loaded. |
| onRetry | () => void | — | Try again was pressed after a failure to load. |
| now | number | Oct 17 2026, 14:00 UTC | The moment the quote's validity is counted from, in ms. |
| barStyle | "solid" | "cells" | "rail" | "solid" | How the budget is drawn: a solid bar, $250 cells cut by a repeating mask, or a 4px rail with $1,000 ticks. |
| pourSpeed | number | 1 | How fast the approved amount pours, as a multiple of the glide's pace from 0.5 to 2; the damping ratio stays the glide's. |
| accent | "cobalt" | "plum" | "mint" | "ink" | string | "cobalt" | The order, its pour and Approve: a named pigment or any CSS colour. |
| formatMoney | (amount) => string | Intl USD | How money is written. |
| height | number | 560 | Tallest the surface grows, in px, before its body scrolls. |
| disabled | boolean | false | Read only. |
| className | string | — | Classes for the surface. |