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.

KQ-635 · ALLOCATION/SLIDER
Waylight Growth · target mixSum 100%
Basin BSN$19,28040%
Fernwork FRN$12,05025%
Coldbrook CBK$9,64020%
Gauge GGE$7,23015%
Mix: Basin BSN 40, Fernwork FRN 25, Coldbrook CBK 20, Gauge GGE 15. Sum 100 percent.

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.