# Input

> A single-line text field with resting, focus, error and disabled looks, built on a native input.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: Forms
- Tags: input, text-field, form, validation
- Docs: https://fancy-ui.rama.app/docs/components/input
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/input

## Import

```svelte
<script lang="ts">
  import { Input } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { Input } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | `""` | Current value; bindable |
| `onValueChange` | `(value: string) => void` | — | Called with the new value on every input event |
| `type` | `"text" \| "email" \| "url" \| "tel" \| "password" \| "search" \| "number"` | `"text"` | Native input type |
| `placeholder` | `string` | — | Shown while the field is empty |
| `disabled` | `boolean` | `false` | Blocks focus and typing; excluded from form submission |
| `readonly` | `boolean` | `false` | Blocks typing but stays focusable and is still submitted, unlike disabled |
| `required` | `boolean` | `false` | Native required |
| `invalid` | `boolean` | `false` | Drives the error border and aria-invalid |
| `id` | `string` | — | Element id |
| `name` | `string` | — | Native name, read on form submission |
| `autocomplete` | `FullAutoFill` | — | Native autocomplete hint; the union from svelte/elements, not an arbitrary string |
| `label` | `string` | — | Accessible name — for a control with no visible Label next to it |
| `class` | `string` | — | Additional CSS classes |
| `ref` | `HTMLInputElement \| null` | `null` | Bindable element reference |

## Examples

### Basic Usage

A single email field with a bound value.

```svelte
<script lang="ts">
	import { Input } from "fancy-ui-svelte";

	let email = $state("");
</script>

<Input bind:value={email} type="email" placeholder="name@example.com" label="Email" />
```

### States

Resting, focus, error and disabled, side by side.

```svelte
<script lang="ts">
	import { Input } from "fancy-ui-svelte";
</script>

<div class="flex w-full max-w-sm flex-col gap-3">
	<Input placeholder="Placeholder…" label="Resting" />
	<Input placeholder="Click or tab to me" label="Focus" />
	<Input value="ab" invalid label="Error" />
	<Input value="Disabled" disabled label="Disabled" />
</div>
```

### Types

Every native input type the component accepts.

```svelte
<script lang="ts">
	import { Input } from "fancy-ui-svelte";
</script>

<div class="flex w-full max-w-sm flex-col gap-3">
	<Input type="text" placeholder="Text" label="Text" />
	<Input type="email" placeholder="name@example.com" label="Email" />
	<Input type="url" placeholder="https://example.com" label="URL" />
	<Input type="tel" placeholder="+1 555 0100" label="Phone" />
	<Input type="password" placeholder="Password" label="Password" />
	<Input type="search" placeholder="Search…" label="Search" />
	<Input type="number" placeholder="0" label="Number" />
</div>
```

### With FormField

Wrapped in FormField and Label — no id or invalid prop needed on Input itself.

```svelte
<script lang="ts">
	// FormField ships from this same wave, built by a different component.
	// It supplies controlId, aria-describedby and aria-invalid to Input
	// through context — Input itself needs no id or invalid prop here.
	// FormField takes `error` text, not a boolean: the presence of error
	// text is what marks the field invalid, and it replaces the help text
	// rather than stacking under it.
	import { FormField } from "fancy-ui-svelte";
	import { Input } from "fancy-ui-svelte";

	let username = $state("ab");
	const error = $derived(username.length < 3 ? "Minimum 3 characters." : undefined);
</script>

<FormField label="Username" required {error} class="w-full max-w-sm">
	<Input bind:value={username} />
</FormField>
```
