crucıble

Quorum

A segmented control: 2–5 options with a single shared-layout pill that springs behind the active choice while its label ignites to full contrast and a faint accent bloom pulses on settle. Real radio semantics — role=radiogroup/radio, roving tabindex, Arrow/Home/End keyboard, focus-visible. Controlled or uncontrolled. The pill snaps under reduced motion.

motionfree

Installation

CLI

npx shadcn@latest add @crucible/quorum

Manual — install dependencies, then copy the source

npm install motion

Props

PropTypeDefaultDescription
optionsQuorumOption[]The options, in order. 2–5 reads best.
valuestringControlled selected value. Omit for uncontrolled use (see defaultValue).
defaultValuestringfirst enabled optionInitial selected value when uncontrolled.
onChange(value: string) => voidFires whenever the selection changes, controlled or not.
aria-labelstring"Choose an option"Accessible name for the group. Provide this OR an external label via aria-labelledby.
accentstringskyThe single cool accent — tints the active label and the settle bloom.
disabledbooleanfalseDisable the whole control (all options unselectable). Individual options can be disabled via QuorumOption.disabled.
pausedbooleanfalseFreeze the spring — the pill still moves, but snaps.
size"sm" | "md" | "lg""md"Visual density.
classNamestring
Also accepts all props of Omit< React.ComponentPropsWithoutRef<"div">, "onChange" | "defaultValue" | "role" >they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, and passes className through.