Number Input
An input that returns a number value and automatically handles invalid inputs.
"use client"
import { NumberInput } from "@/components/ui/number-input"import { useState } from "react"
export function BasicNumberInput() { const [value, setValue] = useState<number | null>(null) return <NumberInput placeholder="Age" value={value} onChange={setValue} />}
Installation
Section titled “Installation”This component relies on other items which must be installed first.
Copy and paste the following code into your project.
components/ui/number-input.tsx
import { Input } from "@/components/ui/input"import { type ComponentProps } from "react"
export function NumberInput({ onChange, value, ...props}: Omit<ComponentProps<typeof Input>, "type" | "onChange" | "value"> & { onChange: (value: number | null) => void value: undefined | null | number}) { return ( <Input {...props} onChange={e => { const number = e.target.valueAsNumber onChange(isNaN(number) ? null : number) }} value={value ?? ""} type="number" /> )}
Update the import paths to match your project setup.
import { useState } from "react"import { NumberInput } from "@/components/ui/NumberInput"
const [value, setValue] = useState<number | null>(null)
<NumberInput value={value} onChange={setValue} />
Examples
Section titled “Examples”"use client"
import { zodResolver } from "@hookform/resolvers/zod"import { useForm } from "react-hook-form"import { toast } from "sonner"import { z } from "zod"import { Button } from "@/components/ui/button"import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage,} from "@/components/ui/form"import { NumberInput } from "@/components/ui/number-input"
const formSchema = z.object({ age: z.number().min(1), favoriteNumber: z.number().min(1).max(100).nullable(),})
export function InputForm() { const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { favoriteNumber: null, }, })
function onSubmit(data: z.infer<typeof formSchema>) { toast("You submitted the following values", { description: ( <pre className="mt-2 w-[320px] rounded-md bg-neutral-950 p-4"> <code className="text-white">{JSON.stringify(data, null, 2)}</code> </pre> ), }) }
return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6"> <FormField control={form.control} name="age" render={({ field }) => ( <FormItem> <FormLabel>Age</FormLabel> <FormControl> <NumberInput {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <FormField control={form.control} name="favoriteNumber" render={({ field }) => ( <FormItem> <FormLabel>Favorite Number</FormLabel> <FormControl> <NumberInput {...field} /> </FormControl> <FormMessage /> <FormDescription>Optional</FormDescription> </FormItem> )} /> <Button type="submit">Submit</Button> </form> </Form> )}