Input

A form input field for collecting user text data.

Installation

Install the component Input in your project using the CLI.

Input.tsx

pnpm dlx behsseui@latest add Input

Install the component manually.

Create a ui folder at the root of the project, then a component folder inside it, and finally a Input.tsx file in that folder.

Copy and paste the following code into your project.

ui/components/Input.tsx

1import { forwardRef, type InputHTMLAttributes } from "react"
2import { cn } from "@/lib/utils"
3
4const Input = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(
5 ({ className, type, ...props }, ref) => {
6 return (
7 <input
8 type={type}
9 className={cn(
10 "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
11 className
12 )}
13 ref={ref}
14 {...props}
15 />
16 )
17 }
18)
19Input.displayName = "Input"
20
21export { Input }
22

Usages

Different variants and use cases for the Input component.

Default

A simple input with a placeholder.

Default.tsx

<Input placeholder="Enter your email" />

With Label

An input with an associated label element.

With Label.tsx

<div className="grid w-full max-w-sm gap-1.5">
  <label htmlFor="email" className="text-sm font-medium">Email</label>
  <Input id="email" type="email" placeholder="Email" />
</div>

Types

Inputs support all native HTML input types.

Types.tsx

<div className="grid w-full max-w-sm gap-4">
  <Input type="email" placeholder="Email" />
  <Input type="password" placeholder="Password" />
  <Input type="number" placeholder="Number" />
  <Input type="tel" placeholder="Phone" />
  <Input type="url" placeholder="URL" />
</div>

Disabled

A disabled input that cannot be interacted with.

Disabled.tsx

<Input disabled placeholder="Disabled" />

With Error

An input styled to indicate a validation error.

Please enter a valid email address.

With Error.tsx

<div className="grid w-full max-w-sm gap-1.5">
  <label htmlFor="email-error" className="text-sm font-medium">Email</label>
  <Input id="email-error" type="email" placeholder="Email" className="border-destructive focus-visible:ring-destructive" />
  <p className="text-sm text-destructive">Please enter a valid email address.</p>
</div>

With Icon

An input with a search icon positioned inside.

With Icon.tsx

import Search from "@/ui/icons/Search"

<div className="relative w-full max-w-sm">
  <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
  <Input className="pl-8" placeholder="Search..." />
</div>

File

A file input for uploading files.

File.tsx

<div className="grid w-full max-w-sm gap-1.5">
  <label htmlFor="picture" className="text-sm font-medium">Picture</label>
  <Input id="picture" type="file" />
</div>

Inline with Button

An input inline with a button for subscribe-style forms.

Inline with Button.tsx

<div className="flex w-full max-w-sm gap-2">
  <Input type="email" placeholder="Email" />
  <Button>Subscribe</Button>
</div>

Grid

Two inputs side by side in a grid layout.

Grid.tsx

<div className="grid grid-cols-2 w-full max-w-sm gap-4">
  <div className="grid gap-1.5">
    <label htmlFor="first" className="text-sm font-medium">First name</label>
    <Input id="first" placeholder="First name" />
  </div>
  <div className="grid gap-1.5">
    <label htmlFor="last" className="text-sm font-medium">Last name</label>
    <Input id="last" placeholder="Last name" />
  </div>
</div>

Required

A required input with a visual indicator.

Required.tsx

<div className="grid w-full max-w-sm gap-1.5">
  <label htmlFor="username" className="text-sm font-medium">
    Username <span className="text-destructive">*</span>
  </label>
  <Input id="username" placeholder="Username" required />
</div>

With Prefix

An input with a static prefix text.

https://

With Prefix.tsx

<div className="flex w-full max-w-sm">
  <span className="inline-flex items-center rounded-l-md border border-r-0 border-input bg-muted px-3 text-sm text-muted-foreground">
    https://
  </span>
  <Input className="rounded-l-none" placeholder="example.com" />
</div>