KQ-718 · NEST/EGG
Nest Egg
A chart of a balance compounding over the years: a principal plus a monthly contribution, compounded monthly at the chosen rate. On mount the curve draws itself from year zero with pathLength on glide over a dashed line of the contributions alone, so the gap between them — the growth — is the picture. The plot is a slider: pressing or dragging reads the value at the nearest year, a cursor and a dot travelling to it on snap while a callout above rolls the year's balance with the contributed and growth split beneath. The rate chips morph the path on glide — every path has the same point count, so the curve bends rather than blinks — against a vertical scale fixed to the highest offered rate, so a higher rate visibly lifts the curve. Arrows step a year, Page keys five, Home and End reach the ends, and a status line announces the settled year, never every year a drag passes through.
Year 20 · 5% · $88,988 · Growth $38,488
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/nest-egg
Props
- principal
- number
- default 0
- The opening balance.
- monthly
- number
- default —
- The monthly contribution, compounded monthly at the chosen rate.
- years
- number
- default 30
- The horizon; the plot has a point per year and the slider runs from 0 to here.
- rates
- number[]
- default [3, 5, 7, 9]
- The rate chips in percent per year; the vertical scale fits the highest so a higher rate lifts the curve rather than rescaling it.
- rate / defaultRate
- number
- default the middle chip
- Controlled or initial annual rate in percent.
- onRateChange
- (rate: number) => void
- default —
- Fires from the chip press or key.
- year / defaultYear
- number
- default years
- Controlled or initial scrub position in years.
- onYearChange
- (year: number) => void
- default —
- Fires from the pointer or key that moved the cursor.
- format
- (value: number) => string
- default Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 })
- Formats every amount. The default pins an explicit locale so server and client agree.
- label
- string
- default —
- Names the chart; printed as the heading and read as the slider's label.
| Prop | Type | Default | Description |
|---|---|---|---|
| principal | number | 0 | The opening balance. |
| monthly | number | — | The monthly contribution, compounded monthly at the chosen rate. |
| years | number | 30 | The horizon; the plot has a point per year and the slider runs from 0 to here. |
| rates | number[] | [3, 5, 7, 9] | The rate chips in percent per year; the vertical scale fits the highest so a higher rate lifts the curve rather than rescaling it. |
| rate / defaultRate | number | the middle chip | Controlled or initial annual rate in percent. |
| onRateChange | (rate: number) => void | — | Fires from the chip press or key. |
| year / defaultYear | number | years | Controlled or initial scrub position in years. |
| onYearChange | (year: number) => void | — | Fires from the pointer or key that moved the cursor. |
| format | (value: number) => string | Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 }) | Formats every amount. The default pins an explicit locale so server and client agree. |
| label | string | — | Names the chart; printed as the heading and read as the slider's label. |