Reasoning Effort
A pill-shaped slider that picks one of a few effort levels, such as Low, Medium, High, and Max. While you drag, a bubble grows out of the track and names the level.
Interactive effort selector
Drag the thumb, click a spot on the track, or use the arrow keys. A bubble with the level name grows out of the track while you drag, and the thumb snaps to the nearest level when you let go.
Selected level: Balanced
Composer model picker
The chat composer's model picker. The slider sits below the model list, the bubble shows the model name with the level, and picking a model keeps the panel open so you can set its effort.
Ask about your workspace…
Level counts
A model's level list sets the ticks. Ticks grow taller toward higher effort, and the tick under the fill turns light. One level still renders, with the thumb parked at the start.
Usage
import { ReasoningEffort } from "@tulipfarm/sprout/reasoning-effort";
const levels = ["Quick", "Balanced", "Thorough", "Maximum"];
const [value, setValue] = useState(1);
<ReasoningEffort levels={levels} value={value} onValueChange={setValue} />const effortLabel = { low: "Low", medium: "Medium", high: "High", max: "Max" };
const index = Math.max(0, model.efforts.indexOf(effort));
{model.efforts.length > 0 && (
<ReasoningEffort
label={model.label}
levels={model.efforts.map((level) => effortLabel[level])}
value={index}
onValueChange={(next) => setEffort(model.efforts[next])}
/>
)}The slider is controlled: pass the chosen index as value and update it in onValueChange. It callsonValueChange as soon as a drag crosses into a new level, not only on release. Hide it when a model has no levels.
Props
levels: level names from lowest to highest effort. Each one gets a tick, spaced evenly. Ticks grow taller toward higher effort.value: the index of the chosen level.onValueChange: called with the new index.label: optional text before the level name in the bubble, such as the model name.aria-label(default "Reasoning effort") oraria-labelledbynames the slider.className: added to the root.
The control is a fixed 256 × 52px: a 32px track with 20px above it for the bubble. It fits the 18rem picker popover with 16px from each outer edge: 15px of padding plus the popover's 1px border.
Accessibility
The track is one role="slider" tab stop. Its value is the index, and aria-valuetext reads the level name. Arrow keys move one level, and Home and End jump to the ends. Keyboard focus shows a 2px --sprout-focus outline.
The bubble is hidden from screen readers because the value text already names the level. When reduced motion is requested, the thumb, bubble, and level change jump instead of tweening. In forced colors mode the track, fill, thumb, and ticks use system colors.
Theme tokens
The fill uses --sprout-primary, so the opt-in TulipFarm theme tints it green. The pill and bubble shade from--sprout-hover to --sprout-active with a--sprout-line edge. The bubble's label uses--sprout-text and its level uses --sprout-muted. The thumb is white; override --sprout-reasoning-effort-thumbto change it.