KQ-635 · ALLOCATION/SLIDER
Allocation Slider
A stack of allocation sliders that always sum to 100. The row under the pointer is exact — its fill and thumb track the finger with duration 0, because direct manipulation must never lag behind the hand — while every other row eases to its new share on glide, so what you hold is instant and what answers is sprung. Whatever the held row gives up is shared out by largest remainder against a snapshot taken when the gesture began, so the whole numbers on screen sum to exactly 100 on every frame and the untouched rows keep their ratios. Each track is a real role="slider": arrows step, Page keys move five, Home and End reach the ends of the pool, and a per-row lock switch takes that row out of the pool on snap.
BSN 40 · FRN 25 · CBK 20 · GGE 15 — Sum 100
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/allocation-slider
Props
- slices
- AllocationSlice[]
- default —
- The rows top to bottom: an id and a label each.
- value / defaultValue
- number[]
- default —
- Controlled or initial whole-percent weights aligned to slices by index; normalised to sum to 100, defaulting to an even split.
- onValueChange
- (values: number[]) => void
- default —
- Fires from the pointer or key that changed the mix, never from a render or a state updater.
- total
- number
- default —
- The portfolio's value; given it, each row prints its cash share in tabular figures.
- format
- (value: number) => string
- default Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 })
- Formats each row's cash share. The default pins an explicit locale so server and client agree.
- step
- number
- default 1
- Percentage points per arrow key; Page keys move five steps.
- lockable
- boolean
- default true
- Renders the per-row lock switch. A locked row never gives and never takes.
- label
- React.ReactNode
- default —
- Visible group heading; omit it and pass aria-label.
| Prop | Type | Default | Description |
|---|---|---|---|
| slices | AllocationSlice[] | — | The rows top to bottom: an id and a label each. |
| value / defaultValue | number[] | — | Controlled or initial whole-percent weights aligned to slices by index; normalised to sum to 100, defaulting to an even split. |
| onValueChange | (values: number[]) => void | — | Fires from the pointer or key that changed the mix, never from a render or a state updater. |
| total | number | — | The portfolio's value; given it, each row prints its cash share in tabular figures. |
| format | (value: number) => string | Intl.NumberFormat("en-US", { style: "currency", currency: "USD", maximumFractionDigits: 0 }) | Formats each row's cash share. The default pins an explicit locale so server and client agree. |
| step | number | 1 | Percentage points per arrow key; Page keys move five steps. |
| lockable | boolean | true | Renders the per-row lock switch. A locked row never gives and never takes. |
| label | React.ReactNode | — | Visible group heading; omit it and pass aria-label. |