- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Card
- Checkbox
- Collapsible
- Combobox
- Context Menu
- Date Picker (Lite)
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP (Lite)
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
A text input component for forms and user data entry with built-in styling and accessibility features.
Your API key is encrypted and stored securely.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputDemo() {
return (
<Field>
<FieldLabel for="input-demo-api-key">API Key</FieldLabel>
<Input id="input-demo-api-key" type="password" placeholder="sk-..." />
<FieldDescription>
Your API key is encrypted and stored securely.
</FieldDescription>
</Field>
)
}Installation
pnpm dlx shadcnui-hono-jsx@latest add inputnpx shadcnui-hono-jsx@latest add inputyarn dlx shadcnui-hono-jsx@latest add inputbunx shadcnui-hono-jsx@latest add inputUsage
import { Input } from "@/components/ui/input"<Input />Basic
import { Input } from "@/components/ui/input"
export function InputBasic() {
return <Input placeholder="Enter text" />
}Field
Use Field, FieldLabel, and FieldDescription to create an input with a
label and description.
Choose a unique username for your account.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputField() {
return (
<Field>
<FieldLabel for="input-field-username">Username</FieldLabel>
<Input
id="input-field-username"
type="text"
placeholder="Enter your username"
/>
<FieldDescription>
Choose a unique username for your account.
</FieldDescription>
</Field>
)
}Field Group
Use FieldGroup to show multiple Field blocks and to build forms.
We'll send updates to this address.
import { Button } from "@/components/ui/button"
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputFieldgroup() {
return (
<FieldGroup>
<Field>
<FieldLabel for="fieldgroup-name">Name</FieldLabel>
<Input id="fieldgroup-name" placeholder="Jordan Lee" />
</Field>
<Field>
<FieldLabel for="fieldgroup-email">Email</FieldLabel>
<Input
id="fieldgroup-email"
type="email"
placeholder="name@example.com"
/>
<FieldDescription>
We'll send updates to this address.
</FieldDescription>
</Field>
<Field orientation="horizontal">
<Button type="reset" variant="outline">
Reset
</Button>
<Button type="submit">Submit</Button>
</Field>
</FieldGroup>
)
}Disabled
Use the disabled prop to disable the input. To style the disabled state, add the data-disabled attribute to the Field component.
This field is currently disabled.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputDisabled() {
return (
<Field data-disabled>
<FieldLabel for="input-demo-disabled">Email</FieldLabel>
<Input
id="input-demo-disabled"
type="email"
placeholder="Email"
disabled
/>
<FieldDescription>This field is currently disabled.</FieldDescription>
</Field>
)
}Invalid
Use the aria-invalid prop to mark the input as invalid. To style the invalid state, add the data-invalid attribute to the Field component.
This field contains validation errors.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputInvalid() {
return (
<Field data-invalid>
<FieldLabel for="input-invalid">Invalid Input</FieldLabel>
<Input id="input-invalid" placeholder="Error" aria-invalid />
<FieldDescription>
This field contains validation errors.
</FieldDescription>
</Field>
)
}File
Use the type="file" prop to create a file input.
Select a picture to upload.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputFile() {
return (
<Field>
<FieldLabel for="picture">Picture</FieldLabel>
<Input id="picture" type="file" />
<FieldDescription>Select a picture to upload.</FieldDescription>
</Field>
)
}Inline
Use Field with orientation="horizontal" to create an inline input.
Pair with Button to create a search input with a button.
import { Button } from "@/components/ui/button"
import { Field } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputInline() {
return (
<Field orientation="horizontal">
<Input type="search" placeholder="Search..." />
<Button>Search</Button>
</Field>
)
}Grid
Use a grid layout to place multiple inputs side by side.
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputGrid() {
return (
<FieldGroup class="grid max-w-sm grid-cols-2">
<Field>
<FieldLabel for="first-name">First Name</FieldLabel>
<Input id="first-name" placeholder="Jordan" />
</Field>
<Field>
<FieldLabel for="last-name">Last Name</FieldLabel>
<Input id="last-name" placeholder="Lee" />
</Field>
</FieldGroup>
)
}Required
Use the required attribute to indicate required inputs.
This field must be filled out.
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputRequired() {
return (
<Field>
<FieldLabel for="input-required">
Required Field <span class="text-destructive">*</span>
</FieldLabel>
<Input
id="input-required"
placeholder="This field is required"
required
/>
<FieldDescription>This field must be filled out.</FieldDescription>
</Field>
)
}Badge
Use Badge in the label to highlight a recommended field.
import { Badge } from "@/components/ui/badge"
import { Field, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputBadge() {
return (
<Field>
<FieldLabel for="input-badge">
Webhook URL{" "}
<Badge variant="secondary" class="ml-auto">
Beta
</Badge>
</FieldLabel>
<Input
id="input-badge"
type="url"
placeholder="https://api.example.com/webhook"
/>
</Field>
)
}Input Group
To add icons, text, or buttons inside an input, use the InputGroup component. See the Input Group component for more examples.
import { InfoIcon } from "@/components/icons"
import { Field, FieldLabel } from "@/components/ui/field"
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
InputGroupText,
} from "@/components/ui/input-group"
export function InputInputGroup() {
return (
<Field>
<FieldLabel for="input-group-url">Website URL</FieldLabel>
<InputGroup>
<InputGroupInput id="input-group-url" placeholder="example.com" />
<InputGroupAddon>
<InputGroupText>https://</InputGroupText>
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<InfoIcon />
</InputGroupAddon>
</InputGroup>
</Field>
)
}Button Group
To add buttons to an input, use the ButtonGroup component. See the Button Group component for more examples.
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import { Field, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function InputButtonGroup() {
return (
<Field>
<FieldLabel for="input-button-group">Search</FieldLabel>
<ButtonGroup>
<Input id="input-button-group" placeholder="Type to search..." />
<Button variant="outline">Search</Button>
</ButtonGroup>
</Field>
)
}Form
A full form example with multiple inputs, a select, and a button.
import { Button } from "@/components/ui/button"
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function InputForm() {
const countries = [
{ label: "United States", value: "us" },
{ label: "United Kingdom", value: "uk" },
{ label: "Canada", value: "ca" },
]
return (
<form class="w-full max-w-sm">
<FieldGroup>
<Field>
<FieldLabel for="form-name">Name</FieldLabel>
<Input
id="form-name"
type="text"
placeholder="Evil Rabbit"
required
/>
</Field>
<Field>
<FieldLabel for="form-email">Email</FieldLabel>
<Input id="form-email" type="email" placeholder="john@example.com" />
<FieldDescription>
We'll never share your email with anyone.
</FieldDescription>
</Field>
<div class="grid grid-cols-2 gap-4">
<Field>
<FieldLabel for="form-phone">Phone</FieldLabel>
<Input id="form-phone" type="tel" placeholder="+1 (555) 123-4567" />
</Field>
<Field>
<FieldLabel for="form-country">Country</FieldLabel>
<Select defaultValue="us">
<SelectTrigger id="form-country">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{countries.map((country) => (
<SelectItem key={country.value} value={country.value}>
{country.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</Field>
</div>
<Field>
<FieldLabel for="form-address">Address</FieldLabel>
<Input id="form-address" type="text" placeholder="123 Main St" />
</Field>
<Field orientation="horizontal">
<Button type="button" variant="outline">
Cancel
</Button>
<Button type="submit">Submit</Button>
</Field>
</FieldGroup>
</form>
)
}RTL
To enable RTL support in shadcn/ui, see the RTL configuration guide.
Your API key is encrypted and stored securely.
مفتاح API الخاص بك مشفر ومخزن بأمان.
מפתח ה-API שלך מוצפן ונשמר בצורה מאובטחת.
// This example sets dir and uses useTranslation because this site is not RTL.
// In an RTL app you won't need them; see the RTL guide.
import {
type Translations,
useTranslation,
} from "@/components/language-selector"
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
const translations: Translations = {
en: {
dir: "ltr",
values: {
apiKey: "API Key",
placeholder: "sk-...",
description: "Your API key is encrypted and stored securely.",
},
},
ar: {
dir: "rtl",
values: {
apiKey: "مفتاح API",
placeholder: "sk-...",
description: "مفتاح API الخاص بك مشفر ومخزن بأمان.",
},
},
he: {
dir: "rtl",
values: {
apiKey: "מפתח API",
placeholder: "sk-...",
description: "מפתח ה-API שלך מוצפן ונשמר בצורה מאובטחת.",
},
},
}
export function InputRtl() {
const { dir, t } = useTranslation(translations, "ar")
return (
<Field dir={dir}>
<FieldLabel for="input-rtl-api-key">{t.apiKey}</FieldLabel>
<Input
id="input-rtl-api-key"
type="password"
placeholder={t.placeholder}
dir={dir}
/>
<FieldDescription>{t.description}</FieldDescription>
</Field>
)
}Notes
- Client-side field state attributes (
data-dirty,data-touched,data-focused,data-filled,data-valid) and the auto-generatedidare not rendered. - Accepts
classinstead ofclassName. - Upstream documentation: shadcn/ui Input. See also Differences from shadcn/ui.