Number Field
A bounded numeric input with decrement and increment stepper buttons.
Basic
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { NumberField } from "@makeplane/propel/components/number-field";
import { Minus, Plus } from "lucide-react";
import * as React from "react";
export default function BasicDemo() {
const [value, setValue] = React.useState<number | null>(2);
return (
<NumberField
aria-label="Number of instances"
magnitude="xl"
min={1}
max={64}
value={value}
onValueChange={setValue}
decrement={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Decrease"
icon={<Icon icon={Minus} />}
/>
}
increment={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Increase"
icon={<Icon icon={Plus} />}
/>
}
/>
);
}Magnitudes
The magnitude axis sets the input height, and each stepper IconButton carries the same magnitude so the group stays flush.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { NumberField } from "@makeplane/propel/components/number-field";
import { Minus, Plus } from "lucide-react";
const MAGNITUDES = ["sm", "md", "lg", "xl"] as const;
export default function MagnitudesDemo() {
return (
<div className="flex flex-wrap items-center gap-3">
{MAGNITUDES.map((magnitude) => (
<NumberField
key={magnitude}
aria-label={`Number of seats (${magnitude})`}
magnitude={magnitude}
defaultValue={4}
min={1}
max={64}
decrement={
<IconButton
prominence="ghost"
tone="neutral"
magnitude={magnitude}
aria-label={`Decrease (${magnitude})`}
icon={<Icon icon={Minus} />}
/>
}
increment={
<IconButton
prominence="ghost"
tone="neutral"
magnitude={magnitude}
aria-label={`Increase (${magnitude})`}
icon={<Icon icon={Plus} />}
/>
}
/>
))}
</div>
);
}Disabled
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { NumberField } from "@makeplane/propel/components/number-field";
import { Minus, Plus } from "lucide-react";
export default function DisabledDemo() {
return (
<NumberField
aria-label="Number of seats"
magnitude="xl"
defaultValue={12}
min={1}
max={64}
disabled
decrement={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Decrease"
icon={<Icon icon={Minus} />}
/>
}
increment={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Increase"
icon={<Icon icon={Plus} />}
/>
}
/>
);
}Formatted
Pass format (an Intl.NumberFormatOptions) to format the displayed value — here as a currency amount stepped by 50.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { IconButton } from "@makeplane/propel/components/icon-button";
import { NumberField } from "@makeplane/propel/components/number-field";
import { Minus, Plus } from "lucide-react";
import * as React from "react";
export default function FormattedDemo() {
const [value, setValue] = React.useState<number | null>(250);
return (
<NumberField
aria-label="Monthly budget"
magnitude="xl"
min={0}
max={10000}
step={50}
value={value}
onValueChange={setValue}
format={{ style: "currency", currency: "USD", maximumFractionDigits: 0 }}
decrement={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Decrease"
icon={<Icon icon={Minus} />}
/>
}
increment={
<IconButton
prominence="ghost"
tone="neutral"
magnitude="xl"
aria-label="Increase"
icon={<Icon icon={Plus} />}
/>
}
/>
);
}Installation
import { NumberField } from "@makeplane/propel/components/number-field";
Props
NumberField
| Prop | Type | Required | Description |
|---|---|---|---|
| magnitude | "sm" | "md" | "lg" | "xl" | Yes | Visual size of the field: controls the input height. Required. |
| decrement | ReactElement<unknown, string | JSXElementConstructor<any>> | Yes | The decrement control (e.g. an `IconButton`), rendered as the field's decrement stepper. It carries its own — localizable — `aria-label`; the field bakes no label or glyph. |
| increment | ReactElement<unknown, string | JSXElementConstructor<any>> | Yes | The increment control (e.g. an `IconButton`), rendered as the field's increment stepper. It carries its own — localizable — `aria-label`; the field bakes no label or glyph. |