Input

Input is a component that allows a user to give input to a form. It can be used to create a form, a search bar, or any other input field.

Submit your email

tsx
'use client'

import { zodResolver } from '@hookform/resolvers/zod'
import {
	Button,
	CardContent,
	CardHeader,
	Card,
	CardTitle,
	Form,
	FormControl,
	FormDescription,
	FormField,
	FormItem,
	FormLabel,
	FormMessage,
	Input,
	toast,
	LabelAsterisk,
} from '@nerdfish/ui'
import { useForm } from 'react-hook-form'
import { z } from 'zod'

const validationSchema = z.object({
	email: z.string().email(),
})

type FormData = z.infer<typeof validationSchema>

export function InputExample() {
	const form = useForm<FormData>({
		resolver: zodResolver(validationSchema),
	})

	function onSubmit(data: FormData) {
		toast.success(`Form submitted successfully: ${data.email}`)
	}

	return (
		<Card>
			<CardHeader>
				<CardTitle>Submit your email</CardTitle>
			</CardHeader>
			<CardContent>
				<Form {...form}>
					<form
						onSubmit={form.handleSubmit(onSubmit)}
						className="gap-md flex flex-col"
						noValidate
					>
						<FormField
							control={form.control}
							name="email"
							render={({ field }) => (
								<FormItem>
									<FormLabel>
										Email
										<LabelAsterisk />
										<FormDescription>Your email address</FormDescription>
									</FormLabel>

									<FormControl>
										<Input
											{...field}
											type="email"
											placeholder="Example: john@doe.com"
										/>
									</FormControl>
									<FormMessage />
								</FormItem>
							)}
						/>

						<Button type="submit">Submit</Button>
					</form>
				</Form>
			</CardContent>
		</Card>
	)
}

Usage

tsx
import { Input } from '@nerdfish/ui'
tsx
<Input name="email" type="email" placeholder="Email" />

Disabled

tsx
'use client'

import { Input } from '@nerdfish/ui'

export function InputDisabledExample() {
	return <Input disabled type="email" placeholder="Email" />
}

Size

tsx
'use client'

import { Input } from '@nerdfish/ui'

export function InputSizeExample() {
	return (
		<div className="w-full space-y-2">
			<Input
				name="input-size-1"
				type="email"
				placeholder="Email"
				inputSize="sm"
			/>
			<Input
				name="input-size-2"
				type="email"
				placeholder="Email"
				inputSize="md"
			/>
			<Input
				name="input-size-3"
				type="email"
				placeholder="Email"
				inputSize="lg"
			/>
		</div>
	)
}

Variant

This is an error message.

tsx
'use client'

import { ErrorDescription, Field, Input, Label } from '@nerdfish/ui'

export function InputVariantsExample() {
	return (
		<div className="space-y-8">
			<Field>
				<Label>Default</Label>
				<Input
					name="email-error"
					variant="default"
					type="email"
					placeholder="Email"
				/>
			</Field>
			<Field>
				<Label>Error</Label>
				<Input
					name="email-error"
					variant="error"
					type="email"
					placeholder="Email"
				/>
				<ErrorDescription>This is an error message.</ErrorDescription>
			</Field>
			<Field>
				<Label>Success</Label>
				<Input
					name="email-success"
					variant="success"
					type="email"
					placeholder="Email"
				/>
			</Field>
			<Field>
				<Label>Bordered</Label>
				<Input
					name="email-bordered"
					variant="bordered"
					type="email"
					placeholder="Email"
				/>
			</Field>
		</div>
	)
}

Icon

tsx
'use client'

import { Input } from '@nerdfish/ui'
import { CheckCircle } from 'lucide-react'

export function InputIconExample() {
	return (
		<div className="w-full space-y-2">
			<Input
				name="input-icon"
				icon={CheckCircle}
				type="email"
				placeholder="Email"
			/>
		</div>
	)
}

Addon

ui.nerdfish.be/
ui.nerdfish.be/
ui.nerdfish.be/
ui.nerdfish.be/
ui.nerdfish.be/
ui.nerdfish.be/
/admin
tsx
'use client'

import { Input, type InputSize, inputVariants } from '@nerdfish/ui'
import { cx, slugify } from '@nerdfish/utils'
import * as React from 'react'

function InputAddon({
	children,
	inputSize = 'md',
}: {
	children: React.ReactNode
	inputSize?: InputSize
}) {
	return (
		<div
			className={cx(
				inputVariants({ inputSize }),
				'bg-foreground/5 inline-flex w-auto font-normal shadow-none',
			)}
		>
			{children}
		</div>
	)
}

export function InputAddonExample() {
	const [value, setValue] = React.useState<string>('')

	return (
		<div className="gap-md flex w-full flex-col">
			<div className="gap-md flex flex-col md:flex-row">
				<Input
					name="slug"
					type="text"
					addOnLeading={<InputAddon inputSize="md">ui.nerdfish.be/</InputAddon>}
					value={value}
					variant="error"
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
				<Input
					name="slug"
					addOnLeading={<InputAddon>ui.nerdfish.be/</InputAddon>}
					type="text"
					value={value}
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
			</div>
			<div className="gap-md flex flex-col md:flex-row">
				<Input
					name="slug"
					type="text"
					addOnLeading={<InputAddon>ui.nerdfish.be/</InputAddon>}
					inputSize="sm"
					value={value}
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
				<Input
					name="slug"
					type="text"
					addOnLeading={<InputAddon>ui.nerdfish.be/</InputAddon>}
					value={value}
					inputSize="sm"
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
			</div>
			<div className="gap-md flex flex-col md:flex-row">
				<Input
					name="slug"
					type="text"
					addOnLeading={<InputAddon inputSize="lg">ui.nerdfish.be/</InputAddon>}
					inputSize="lg"
					value={value}
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
				<Input
					name="slug"
					type="text"
					addOnLeading={<InputAddon inputSize="lg">ui.nerdfish.be/</InputAddon>}
					value={value}
					inputSize="lg"
					onChange={(e) => setValue(slugify(e.target.value, true))}
					autoComplete="off"
				/>
			</div>
			<Input
				name="slug"
				type="text"
				addOnTrailing={<InputAddon>/admin</InputAddon>}
				value={value}
				onChange={(e) => setValue(slugify(e.target.value, true))}
				autoComplete="off"
			/>
		</div>
	)
}

Custom Styles

tsx
'use client'

import { Input } from '@nerdfish/ui'
import { SearchIcon } from 'lucide-react'

export function InputCustomStylesExample() {
	return (
		<div className="flex h-[240px] w-[340px] items-center justify-center rounded-2xl bg-gradient-to-tr from-pink-500 to-yellow-500 px-8 text-white shadow-lg">
			<Input
				icon={SearchIcon}
				className="bg-popover text-foreground"
				type="text"
				placeholder="Search for anything"
			/>
		</div>
	)
}