Overview
The Input component is a composite component that provides a flexible and feature-rich text input interface. It consists of multiple subcomponents that work together to create sophisticated input experiences.
Installation
npm install @svelte-atoms/core
Basic Usage
<script>
import { Input } from '@svelte-atoms/core/components/input';
let value = $state('');
</script>
<Input.Root>
<Input.Control bind:value placeholder="Enter text..." />
</Input.Root>
Subcomponents
The Input component is made up of several subcomponents:
- Input.Root - Container for the input and related elements
- Input.Control - The actual input element
- Input.Icon - Icon elements displayed inside the input
- Input.Placeholder - Custom placeholder that appears when input is empty
Examples
Input with Icons
<script>
import { Input } from '@svelte-atoms/core/components/input';
import { Label } from '@svelte-atoms/core/components/label';
</script>
<Label for="price-input">Price</Label>
<Input.Root>
<Input.Icon class="text-foreground box-content px-0">$</Input.Icon>
<Input.Control id="price-input" class="border-border box-content border-x px-2 py-2" />
<Input.Icon class="text-foreground box-content px-2">.00</Input.Icon>
</Input.Root>
Input with Custom Placeholder
<Input.Root>
<Input.Control />
<Input.Placeholder class="text-foreground/20 pl-2">Enter your name</Input.Placeholder>
</Input.Root>
Different Input Types
<!-- Text input -->
<Input.Root>
<Input.Control type="text" />
</Input.Root>
<!-- Number input -->
<Input.Root>
<Input.Control type="number" bind:number />
</Input.Root>
<!-- Date input -->
<Input.Root>
<Input.Control type="date" bind:date />
</Input.Root>
<!-- File input -->
<Input.Root>
<Input.Control type="file" bind:files />
</Input.Root>
Controlled Input
<script>
let value = $state('');
let files = $state([]);
let date = $state(null);
let number = $state(0);
</script>
<Input.Root>
<Input.Control
bind:value
bind:files
bind:date
bind:number
/>
</Input.Root>
Input.Root Props
value
string | number | string[] | null
The current value of the input. Can be bound for two-way binding.
For checkbox/radio inputs, indicates checked state.
For file inputs, the array of selected files.
The preset key used for styling.
Additional CSS classes to apply to the root container.
children
Snippet<[{ input: InputBond }]>
Child components with access to the input bond.
Input.Control Props
The input value. Bindable for two-way data binding.
Array of files for file inputs. Bindable.
Date value for date inputs. Bindable.
Number value for number inputs. Bindable.
Checked state for checkbox/radio inputs. Bindable.
type
HTMLInputTypeAttribute | null
default:"'text'"
The HTML input type (text, number, date, email, password, file, etc.).
Additional CSS classes for the input element.
preset
string
default:"'input.control'"
The preset key for the input control.
Change event handler. Receives the event and options object with value, files, date, number, and checked properties.
Input event handler. Receives the event and options object with value, files, date, number, and checked properties.
Input.Icon Props
CSS classes for the icon container.
The icon component to render.
Text or components to render as the icon.
Input.Placeholder Props
CSS classes for the placeholder element.
Default Styling
Input.Root
border-border
text-foreground
bg-input
relative
flex
h-10
w-auto
items-center
overflow-hidden
rounded-md
border
Input.Control
text-foreground
placeholder:text-muted-foreground
h-full
w-full
flex-1
bg-transparent
px-2
leading-1
outline-none
Input.Icon
border-border
flex
aspect-square
h-full
items-center
justify-center
bg-transparent
text-sm
leading-0
Input.Placeholder
text-muted-foreground
pointer-events-none
absolute
inset-0
flex
h-full
w-full
items-center
px-1
leading-1
outline-none
Event Handling
The Input.Control component provides enhanced event handlers:
<script>
function handleInput(ev, options) {
console.log('Value:', options.value);
console.log('Files:', options.files);
console.log('Date:', options.date);
console.log('Number:', options.number);
}
function handleChange(ev, options) {
console.log('Changed:', options);
}
</script>
<Input.Root>
<Input.Control
type="text"
oninput={handleInput}
onchange={handleChange}
/>
</Input.Root>
TypeScript Support
interface InputRootProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>
extends HtmlAtomProps<E, B>, InputRootExtendProps {
value?: string | number | string[] | null;
checked?: boolean;
files?: File[] | null;
children?: Snippet<[]>;
}
interface InputControlProps<B extends Base = Base>
extends Override<HtmlAtomProps<'input', B>, InputControlBaseProps>, InputControlExtendProps {}
Integration with Forms
<script>
import { Form } from '@svelte-atoms/core/components/form';
import { Input } from '@svelte-atoms/core/components/input';
</script>
<Form.Root>
<Form.Field name="email">
<Form.Field.Label>Email</Form.Field.Label>
<Input.Root>
<Form.Field.Control base={Input.Control} type="email" />
</Input.Root>
</Form.Field>
</Form.Root>
Input Bond System
The Input component uses a bond system to manage state across subcomponents:
- Automatically syncs value between Input.Root and Input.Control
- Manages placeholder visibility based on input value
- Handles different input types (text, file, date, number)
- Coordinates events and state updates
Accessibility
- Uses semantic
<input> element
- Supports all native input attributes (aria-*, required, disabled, etc.)
- Placeholder is hidden from screen readers when using Input.Placeholder
- Compatible with form labels via
id attribute
Best Practices
- Always use Input.Root as container: It manages the bond and state
- Bind appropriate value types: Use
bind:value for text, bind:number for numbers, bind:files for files
- Use with Label component: Associate labels with inputs using
for attribute
- Handle validation: Combine with Form.Field for validation support
- Customize with presets: Define input variants in your preset configuration
Related Components
- Form - For form management and validation
- Label - For input labels
- Textarea - For multi-line text input