MUINumberStepper
MUINumberStepper is MUINumberInput with
always-visible - / + buttons flanking the input instead of the native
browser steppers. Every numeric behaviour — number | null value,
onlyIntegers, nonNegative, maxDecimalPlaces, stepAmount, min / max
clamping, validation and labelling is delegated to MUINumberInput. This
component only adds the buttons and disables the decrement / increment button
once its min / max bound is reached.
caption renders custom content (text, an icon, or both) just below the
value — e.g. a unit label like "kg" or "Degrees". captionProps styles the
Box wrapping caption — its sx is merged with the component's own base
caption styles (position, spacing, font size, color) rather than replacing
them.
Usage
import MUINumberStepper, { MUINumberStepperProps } from '@nish1896/mui-components/mui/number-stepper';const [quantity, setQuantity] = useState<number | null>(1);
<MUINumberStepper
fieldName="quantity"
value={quantity}
onValueChange={({ newValue }) => setQuantity(newValue)}
onlyIntegers
min={1}
max={10}
/>Customizing icons
decrementIcon/incrementIcon— replace the default-/+icons.swapButtons— swap the button positions, so the increment (+) button sits on the left of the input and the decrement (-) button on the right.iconButtonProps— forwarded to both stepper IconButtons (e.g.size,sx). Interaction and accessibility props are managed by the component.
import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline';
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
<MUINumberStepper
fieldName="temperature"
value={temp}
onValueChange={({ newValue }) => setTemp(newValue)}
decrementIcon={<RemoveCircleOutlineIcon />}
incrementIcon={<AddCircleOutlineIcon />}
iconButtonProps={{ size: 'medium', sx: { color: 'primary.main' } }}
/>API
MUINumberStepperProps extends MUINumberInputProps
(minus showMarkers) and also accepts most
TextFieldProps, with some props
excluded, including type, multiline and rows.
Props marked with * are required.
| Name | Type | Description |
|---|---|---|
fieldName* | string | Name/path of the field. Used to derive the id, the default label, and the name attribute. This prop is required for all components. |
value | number | null | Current numeric value of the field. undefined/null render an empty input. |
onValueChange* | ({ newValue, event }) => void | Called on every accepted numeric change. newValue is null when the input is cleared. |
min | number | Lower bound for the value. Stepping (arrow keys / markers) clamps to this and the value is clamped on blur. nonNegative sets the lower bound to 0, but min overrides it when set. |
max | number | Upper bound for the value. Stepping (arrow keys / markers) clamps to this and the value is clamped on blur. |
nonNegative | boolean | When true, negative values cannot be entered. |
onlyIntegers | boolean | When true, decimal input is not allowed. Cannot be combined with maxDecimalPlaces. |
maxDecimalPlaces | number | Maximum number of decimal places accepted while typing. |
stepAmount | number | Amount the value changes on Arrow Up/Down key presses. |
decrementIcon | ReactNode | Custom icon for the decrement ( -) button.Default: Material UI Remove icon |
incrementIcon | ReactNode | Custom icon for the increment ( +) button.Default: Material UI Add icon |
swapButtons | boolean | When true, swaps both the icons and the behaviour of the two buttons: the left button increments and the right button decrements. |
iconButtonProps | IconButtonProps | IconButtonProps forwarded to both stepper IconButtons — custom size, sx, etc. The interaction/accessibility essentials (onClick, onMouseDown, edge, disabled, aria-label) are controlled by the component. |
caption | ReactNode | Content rendered under the value. E.g. an icon + label. |
captionProps | BoxProps | Props forwarded to the Box wrapping caption — e.g. a custom sx to override its position, spacing, font size or color. Merged with the component's own base caption styles rather than replacing them, and accepts any sx form — object, array, or function. Has no effect when caption isn't provided. |
label | ReactNode | Label displayed for the field. Defaults to a human-readable label derived from fieldName, e.g. firstName becomes "First Name". |
showLabelAboveFormField | boolean | When true, renders the field label above the form field in the FormLabel component, instead of inside or beside it. |
formLabelProps | FormLabelProps | FormLabelProps forwarded to the internal FormLabel. The id is managed by the component. Multiple fields can be configured using the ConfigProvider component. |
hideLabel | boolean | When true, hides the rendered field label while preserving accessible labeling where possible. |
required | boolean | Indicates that the field is mandatory by adding an asterisk symbol (*) to the form label and setting the relevant accessibility attributes. |
errorMessage | string | string[] | Validation error for the field — pass a single message string, or a string[] when the field can fail multiple rules at once (every message is shown together). A non-empty string or array puts the field in an error state; undefined/''/[] clear it.Normalize your form library's error shape to this at the call site (e.g. an RHF FieldError via its .message). Use renderError to customize how the message(s) are rendered. |
renderError | (errors: string[]) => ReactNode | Custom renderer for the resolved error message(s), called only when the field is in an error state. Always receives a string[] — use errors[0] for the common single-message case, or map over errors when a field fails several rules. By default a single message renders as text and multiple messages render on separate lines. |
hideErrorMessage | boolean | If true, hides the error message text while keeping the field in an error state. |
formHelperTextProps | FormHelperTextProps | FormHelperTextProps forwarded to the internal FormHelperText. The id is managed by the component. Multiple fields can be configured using the ConfigProvider component. |
customIds | { field, label, helperText, error } | Overrides the default field, label, helper text, and error IDs used for accessibility. |
Playground
Integrated with TanStack Form — covers
onlyIntegers, nonNegative, maxDecimalPlaces, stepAmount, min / max
bounds, swapButtons, caption/captionProps, with validation surfaced
through errorMessage.