Split Allocator

Keeps splits adding up to exactly the total, showing what's left as you type and rounding automatic splits so nothing is off by one.

StopsSplit adds up to 101%

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/split-allocator.json

The files land in your project. They're yours to edit.

Usage

split-allocator-usage.tsx
import { SplitAllocator } from "@/components/ui/split-allocator"

<SplitAllocator label="Equity split" items={founders} defaultValue={{ priya: 50, rahul: 38 }} />

What it catches

  • Totals over or under (99%, 101%)
  • Rows left on 0
  • Remainder, assignable to any row in one tap
  • Automatic splits that would drift by rounding, fixed with largest-remainder

Props

SplitAllocator props
PropTypeDefault
items* (required)

Rows to split across.

SplitItem[]—
total

The amount being split: 100 for percentages, or a sum of money.

number100
precision

Decimal places each share is rounded to (2 for rupees and paise).

number0
prefix

Shown before each amount, e.g. "₹".

string""
suffix

Shown after each amount, e.g. "%".

string"%"
locale

Number formatting locale.

string"en-IN"
label

Visible legend.

string"Split"
value

Controlled shares by item id.

Record<string, number>—
defaultValue

Initial shares when uncontrolled.

Record<string, number>{}
onValueChange

Called with every row's share on each change.

(value: Record<string, number>) => void—
remainingText

Templates: `{amount}`, `{total}`, `{label}` and `{labels}` are filled in.

string"{amount} left to assign"
overText

Shown when the parts exceed the total.

string"Over by {amount}."
doneText

Shown when the parts add up exactly.

string"All {total} assigned"
zeroText

Warning for a row left on zero.

string"{labels} would get nothing."
giveRestLabel

Label of the give-the-rest fix.

string"Give the remaining {amount} to {label}"
takeOverLabel

Label of the take-the-excess fix.

string"Take the extra {amount} from {label}"
scaleLabel

Label of the scale-to-total fix.

string"Scale down to fit"
evenLabel

Label of the split-evenly button.

string"Split evenly"

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Group labelled by its label; each row input has a <label>
  • aria-invalid when over the total; status in a polite live region via aria-describedby
  • Give-rest/take-over buttons have aria-labels with the amount
  • Progress bar is aria-hidden; the numbers are in text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Even and proportional splits only; custom rules are yours
  • Uses decimal precision you set; currency minor units must match

What it stops

Split adds up to 101%

Also known as

split · allocation · split bill · percentages · splitwise · revenue share · budget allocation · rounding

Field type

Dependencies

Pairs well with