8.0k

Input

A text input component for forms and user data entry with built-in styling and accessibility features.

Epicenter

Local-first, open source apps

Special Sponsor

Your API key is encrypted and stored securely.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-demo-api-key">API Key</Field.Label>
	<Input id="input-demo-api-key" type="password" placeholder="sk-..." />
	<Field.Description>Your API key is encrypted and stored securely.</Field.Description>
</Field.Field>

Installation

pnpm dlx shadcn-svelte@latest add input

Usage

<script lang="ts">
  import { Input } from "$lib/components/ui/input/index.js";
</script>
<Input />

Basic

<script lang="ts">
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Input placeholder="Enter text" />

Field

Use Field.Field, Field.Label, and Field.Description to create an input with a label and description.

Choose a unique username for your account.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-field-username">Username</Field.Label>
	<Input id="input-field-username" type="text" placeholder="Enter your username" />
	<Field.Description>Choose a unique username for your account.</Field.Description>
</Field.Field>

Field Group

Use Field.Group to show multiple Field.Field blocks and to build forms.

We'll send updates to this address.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Button } from "$lib/components/ui/button/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Group>
	<Field.Field>
		<Field.Label for="fieldgroup-name">Name</Field.Label>
		<Input id="fieldgroup-name" placeholder="Jordan Lee" />
	</Field.Field>
	<Field.Field>
		<Field.Label for="fieldgroup-email">Email</Field.Label>
		<Input id="fieldgroup-email" type="email" placeholder="name@example.com" />
		<Field.Description>We'll send updates to this address.</Field.Description>
	</Field.Field>
	<Field.Field orientation="horizontal">
		<Button type="reset" variant="outline">Reset</Button>
		<Button type="submit">Submit</Button>
	</Field.Field>
</Field.Group>

Disabled

Use the disabled prop to disable the input. To style the disabled state, add the data-disabled attribute to the Field.Field component.

This field is currently disabled.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field data-disabled>
	<Field.Label for="input-demo-disabled">Email</Field.Label>
	<Input id="input-demo-disabled" type="email" placeholder="Email" disabled />
	<Field.Description>This field is currently disabled.</Field.Description>
</Field.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.Field component.

This field contains validation errors.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field data-invalid>
	<Field.Label for="input-invalid">Invalid Input</Field.Label>
	<Input id="input-invalid" placeholder="Error" aria-invalid />
	<Field.Description>This field contains validation errors.</Field.Description>
</Field.Field>

File

Use the type="file" prop to create a file input.

Select a picture to upload.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="picture">Picture</Field.Label>
	<Input id="picture" type="file" />
	<Field.Description>Select a picture to upload.</Field.Description>
</Field.Field>

Inline

Use Field.Field with orientation="horizontal" to create an inline input. Pair with Button to create a search input with a button.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Button } from "$lib/components/ui/button/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field orientation="horizontal">
	<Input type="search" placeholder="Search..." />
	<Button>Search</Button>
</Field.Field>

Grid

Use a grid layout to place multiple inputs side by side.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Group class="grid max-w-sm grid-cols-2">
	<Field.Field>
		<Field.Label for="first-name">First Name</Field.Label>
		<Input id="first-name" placeholder="Jordan" />
	</Field.Field>
	<Field.Field>
		<Field.Label for="last-name">Last Name</Field.Label>
		<Input id="last-name" placeholder="Lee" />
	</Field.Field>
</Field.Group>

Required

Use the required attribute to indicate required inputs.

This field must be filled out.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-required">
		Required Field <span class="text-destructive">*</span>
	</Field.Label>
	<Input id="input-required" placeholder="This field is required" required />
	<Field.Description>This field must be filled out.</Field.Description>
</Field.Field>

Badge

Use Badge in the label to highlight a recommended field.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import { Badge } from "$lib/components/ui/badge/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-badge">
		Webhook URL
		<Badge variant="secondary" class="ml-auto">Beta</Badge>
	</Field.Label>
	<Input id="input-badge" type="url" placeholder="https://api.example.com/webhook" />
</Field.Field>

Input Group

To add icons, text, or buttons inside an input, use the InputGroup component. See the Input Group component for more examples.

https://
<script lang="ts">
	import InfoIcon from "@lucide/svelte/icons/info";
	import * as Field from "$lib/components/ui/field/index.js";
	import * as InputGroup from "$lib/components/ui/input-group/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-group-url">Website URL</Field.Label>
	<InputGroup.Root>
		<InputGroup.Input id="input-group-url" placeholder="example.com" />
		<InputGroup.Addon>
			<InputGroup.Text>https://</InputGroup.Text>
		</InputGroup.Addon>
		<InputGroup.Addon align="inline-end">
			<InfoIcon />
		</InputGroup.Addon>
	</InputGroup.Root>
</Field.Field>

Button Group

To add buttons to an input, use the ButtonGroup component. See the Button Group component for more examples.

<script lang="ts">
	import * as ButtonGroup from "$lib/components/ui/button-group/index.js";
	import * as Field from "$lib/components/ui/field/index.js";
	import { Button } from "$lib/components/ui/button/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
</script>
 
<Field.Field>
	<Field.Label for="input-button-group">Search</Field.Label>
	<ButtonGroup.Root>
		<Input id="input-button-group" placeholder="Type to search..." />
		<Button variant="outline">Search</Button>
	</ButtonGroup.Root>
</Field.Field>

Form

A full form example with multiple inputs, a select, and a button.

We'll never share your email with anyone.

<script lang="ts">
	import * as Field from "$lib/components/ui/field/index.js";
	import * as Select from "$lib/components/ui/select/index.js";
	import { Button } from "$lib/components/ui/button/index.js";
	import { Input } from "$lib/components/ui/input/index.js";
 
	const countries = [
		{ value: "us", label: "United States" },
		{ value: "uk", label: "United Kingdom" },
		{ value: "ca", label: "Canada" },
	];
 
	let country = $state("us");
</script>
 
<form class="w-full max-w-sm">
	<Field.Group>
		<Field.Field>
			<Field.Label for="form-name">Name</Field.Label>
			<Input id="form-name" type="text" placeholder="Evil Rabbit" required />
		</Field.Field>
		<Field.Field>
			<Field.Label for="form-email">Email</Field.Label>
			<Input id="form-email" type="email" placeholder="john@example.com" />
			<Field.Description>We'll never share your email with anyone.</Field.Description>
		</Field.Field>
		<div class="grid grid-cols-2 gap-4">
			<Field.Field>
				<Field.Label for="form-phone">Phone</Field.Label>
				<Input id="form-phone" type="tel" placeholder="+1 (555) 123-4567" />
			</Field.Field>
			<Field.Field>
				<Field.Label for="form-country">Country</Field.Label>
				<Select.Root type="single" items={countries} bind:value={country}>
					<Select.Trigger id="form-country">
						<Select.Value />
					</Select.Trigger>
					<Select.Content>
						<Select.Group>
							{#each countries as item (item.value)}
								<Select.Item value={item.value} label={item.label}>{item.label}</Select.Item>
							{/each}
						</Select.Group>
					</Select.Content>
				</Select.Root>
			</Field.Field>
		</div>
		<Field.Field>
			<Field.Label for="form-address">Address</Field.Label>
			<Input id="form-address" type="text" placeholder="123 Main St" />
		</Field.Field>
		<Field.Field orientation="horizontal">
			<Button type="button" variant="outline">Cancel</Button>
			<Button type="submit">Submit</Button>
		</Field.Field>
	</Field.Group>
</form>