KQ-1773 · SPEND/GUARD

Spend Guard

A budget-alerts panel for a project's cloud spend this month: one bar carries the spend as a fill, the forecast to month end as a hatch, a hairline at the budget and a marker per alert threshold with its recipients' avatars riding on its head, while a month strip below pins each threshold to the day it fired or will fire at the current pace, joined by a leader. Dragging a marker follows the pointer 1:1 and rubber-bands past the axis, the avatars follow on springs.snap and the date pin trails on springs.glide, and release snaps to a whole percent on snap with the throw's velocity; crossing what is already spent flips the head on springs.flick. Every marker is a slider (arrows one percent, Shift five, Page keys ten, Home and End), the recipients menu is a real menu, and an optional hard limit says plainly what stops.

KQ-1773 · SPEND/GUARD

Waylight · cloud spend

October 2026 · budget $5,000

Forecast over budget

Spent

$2,904

58% of budget

Forecast

$5,286

106% of budget

Pace

$170/day

last 7 days

Day

17 of 31

14 left

Spent $2,904 of a $5,000 budget, 58%, on day 17 of 31. At $170 a day the month ends near $5,286, 106% of budget. Each alert is a slider: arrow keys move it one percent, Shift five, Page Up and Page Down ten.

50%
80%
100%
Stop

Alerts · 3 of 5

  • 50%$2,500fired 15 Oct
    Joel
  • 80%$4,000fires 24 Oct
    JoelMara
  • 100%$5,000fires 30 Oct
    JoelMaraRuth

Hard limit

Stops spending at $6,250

$6,250
not this month

At $6,250: New deployments pause and preview environments scale to zero. Production keeps serving, and nothing is deleted.

All changes saved

3 alerts · budget $5,000 · stops at $6,250

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/spend-guard

Props

markerStyle
"pin" | "flag" | "tick"
default "pin"
How a threshold marker is drawn: a round head carrying the avatars, a flag off the stem, or a hairline tick.
barHeight
number
default 20
Thickness of the spend bar in px; markers and the month strip scale with it.
palette
"cobalt" | "ember" | "moss" | "mono"
default "cobalt"
Tone of the spend fill, forecast hatch and markers; the hard limit keeps its danger tone.
budget
number
default 5000
The monthly budget, in the currency format prints.
thresholds / defaultThresholds
SpendThreshold[]
default — / defaultSpendThresholds
The alert thresholds, controlled or initial: { id, percent (of budget), recipients (ids) }.
onThresholdChange
(thresholds: SpendThreshold[], id: string) => void
default —
Fires from the drag, key, add, remove or recipient change that changed the thresholds, with all of them and the id that changed.
recipients
SpendRecipient[]
default defaultSpendRecipients
Everyone who can be alerted: { id, name, role?, hue? }.
onRecipientsChange
(thresholdId: string, recipientIds: string[]) => void
default —
A threshold's recipients changed, with the new ids.
hardLimit / defaultHardLimit
number | null
default — / null
The amount at which spending stops, controlled or initial; null for none.
onHardLimitChange
(amount: number | null) => void
default —
The hard limit was switched on, moved or switched off.
hardLimitEffect
string
default "New deployments pause and preview environments scale to zero. Production keeps serving, and nothing is deleted."
One plain sentence: what stops at the hard limit and what keeps running.
daily
number[]
default defaultSpendDaily
Spend per day of the current month so far, day 1 first; the pace is the mean of the last seven.
now
number
default defaultSpendNow (17 Oct 2026)
The current time in ms. Dates are read in UTC; never read from the clock.
format
(amount: number) => string
default US dollars, no cents
Formats every amount.
onSave
(config: SpendConfig) => void | Promise<void>
default —
Save was pressed with { thresholds, hardLimit }; return a promise to show Saving… and its outcome.
status
"ready" | "loading" | "empty" | "error"
default "ready"
Whether the spend data has arrived. The bar and its markers stay in every state.
onRetry
() => void
default —
Try again was pressed after the spend failed to load.
project
string
default "Waylight"
The project, in the heading.
height
number
default 540
Height of the surface in px; its body scrolls inside.
disabled
boolean
default false
Nothing can be moved, added or saved.
className
string
default —
Classes for the outer surface.