Components
- AccordionNew
- Alert
- Alert DialogNew
- AutocompleteNew
- AvatarNew
- Badge
- Breadcrumb
- Button
- CalendarNew
- CardNew
- Checkbox
- Checkbox GroupNew
- CollapsibleNew
- ComboboxNew
- CommandNew
- Context MenuNew
- Date PickerNew
- DialogNew
- DrawerNew
- EmptyNew
- FieldNew
- FieldsetNew
- FormNew
- FrameNew
- GroupNew
- Input
- Input GroupNew
- KbdNew
- Label
- MenuNew
- MeterNew
- Number Field
- OTP FieldNew
- Pagination
- PopoverNew
- Preview CardNew
- Progress
- Radio Group
- Scroll AreaNew
- Select
- Separator
- SheetNew
- SkeletonNew
- Slider
- Spinner
- StepperNew
- Switch
- Table
- TabsNew
- Textarea
- ToastNew
- ToggleNew
- Toggle GroupNew
- ToolbarNew
- Tooltip
Number Field
A numeric input element with increment and decrement buttons, and a scrub area.
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={0}>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
Usage
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
NumberFieldScrubArea,
} from "mako-ui/components/number-field"<NumberField defaultValue={0}>
<NumberFieldScrubArea label="Quantity" />
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>API Reference
NumberField
Root component.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Controls the size of all child components via context |
NumberFieldGroup
Container for the input and buttons.
NumberFieldInput
Input element for the number value.
NumberFieldIncrement
Button to increment the value. Includes plus icon.
NumberFieldDecrement
Button to decrement the value. Includes minus icon.
NumberFieldScrubArea
Draggable area for scrubbing the value.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Label text displayed in the scrub area |
Examples
For accessible labelling and validation, prefer using the Field component to wrap number fields. See the related example: Number field.
Small Size
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={0} size="sm">
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
Large Size
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={0} size="lg">
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
Disabled
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={42} disabled>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
With External Label
import { Label } from "mako-ui/components/label";
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
import { useId } from "react";
export default function Particle() {
const id = useId();
return (
<div className="flex flex-col items-start gap-2">
<Label htmlFor={id}>Quantity</Label>
<NumberField defaultValue={0} id={id}>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
</div>
);
}
With Scrub
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
NumberFieldScrubArea,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={0}>
<NumberFieldScrubArea label="Quantity" />
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
With Range
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField defaultValue={5} max={10} min={0}>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
With Formatted Value
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<NumberField
defaultValue={0}
format={{ currency: "USD", style: "currency" }}
>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput aria-label="Quantity" />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
);
}
With Step
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
NumberFieldScrubArea,
} from "mako-ui/components/number-field";
export default function Particle() {
return (
<div className="flex flex-col gap-6">
<NumberField defaultValue={0} step={10}>
<NumberFieldScrubArea label="Step 10" />
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
<NumberField defaultValue={0} step={0.1}>
<NumberFieldScrubArea label="Step 0.1" />
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
</div>
);
}
Form Integration
"use client";
import { Button } from "mako-ui/components/button";
import { Field } from "mako-ui/components/field";
import { Form } from "mako-ui/components/form";
import {
NumberField,
NumberFieldDecrement,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
NumberFieldScrubArea,
} from "mako-ui/components/number-field";
import type { FormEvent } from "react";
import { useState } from "react";
import { z } from "zod";
const schema = z.object({
quantity: z.coerce
.number({ message: "Please enter a quantity." })
.min(1, { message: "Quantity must be at least 1." })
.max(100, { message: "Maximum quantity is 100." }),
});
type Errors = Record<string, string | string[]>;
async function submitForm(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const result = schema.safeParse(Object.fromEntries(formData));
if (!result.success) {
const { fieldErrors } = z.flattenError(result.error);
return { errors: fieldErrors as Errors };
}
return {
data: result.data,
errors: {} as Errors,
};
}
export default function Particle() {
const [loading, setLoading] = useState(false);
const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
setLoading(true);
const response = await submitForm(event);
await new Promise((r) => setTimeout(r, 800));
setLoading(false);
if (Object.keys(response.errors).length === 0) {
alert(`Quantity: ${response.data?.quantity}`);
}
};
return (
<Form className="flex w-full max-w-64 flex-col gap-4" onSubmit={onSubmit}>
<Field name="quantity">
<NumberField defaultValue={1} max={100} min={1}>
<NumberFieldScrubArea label="Quantity" />
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>
</Field>
<Button loading={loading} type="submit">
Submit
</Button>
</Form>
);
}