Primitive single-line text input component that accepts standard HTML attributes.
Import
import { Input } from "heroui-solid";For validation, labels, and error messages, see TextField.
Usage
import { Input } from "heroui-solid"
export function Basic() {
return <Input aria-label="Name" class="w-64" placeholder="Enter your name" />
}Input Types
import { Input, Label } from "heroui-solid"
export function Types() {
return (
<div class="flex w-80 flex-col gap-4">
<div class="flex flex-col gap-1">
<Label for="input-type-email">Email</Label>
<Input
id="input-type-email"
placeholder="jane@example.com"
type="email"
/>
</div>
<div class="flex flex-col gap-1">
<Label for="input-type-number">Age</Label>
<Input id="input-type-number" min={0} placeholder="30" type="number" />
</div>
<div class="flex flex-col gap-1">
<Label for="input-type-password">Password</Label>
<Input
id="input-type-password"
placeholder="••••••••"
type="password"
/>
</div>
</div>
)
}Controlled
Standalone inputs are controlled with Solid's native onInput event (HeroUI React
uses React's onChange, which fires per keystroke — Solid's onChange fires on blur).
import { Input } from "heroui-solid"
import { createSignal } from "solid-js"
export function Controlled() {
const [value, setValue] = createSignal("heroui.com")
return (
<div class="flex w-80 flex-col gap-2">
<Input
aria-label="Domain"
placeholder="domain"
value={value()}
onInput={(event) => setValue(event.currentTarget.value)}
/>
<span class="px-1 text-sm text-muted">
https://{value() || "your-domain"}
</span>
</div>
)
}Full Width
import { Input } from "heroui-solid"
export function FullWidth() {
return (
<div class="w-[400px] space-y-3">
<Input fullWidth placeholder="Full width input" />
</div>
)
}Variants
The Input component supports two visual variants:
primary(default) - Standard styling with shadow, suitable for most use casessecondary- Lower emphasis variant without shadow, suitable for use in Surface components
import { Input } from "heroui-solid"
export function Variants() {
return (
<div class="flex w-[240px] flex-col gap-2">
<Input fullWidth placeholder="Primary input" variant="primary" />
<Input fullWidth placeholder="Secondary input" variant="secondary" />
</div>
)
}In Surface
When used inside a Surface component, use variant="secondary" to apply the lower emphasis variant suitable for surface backgrounds.
import { Input, Surface } from "heroui-solid"
export function OnSurface() {
return (
<Surface class="flex h-[180px] w-[280px] items-center justify-center rounded-3xl bg-surface p-4">
<Input class="w-full" placeholder="Your name" variant="secondary" />
</Surface>
)
}Related Components
- TextField: Composition-friendly fields with labels and validation
- TextArea: Multiline text input
- Label: Accessible label for form controls
Styling
Passing Tailwind CSS classes
import { Input, Label } from "heroui-solid";
function CustomInput() {
return (
<div class="flex flex-col gap-2">
<Label htmlFor="custom-input">Project name</Label>
<Input
id="custom-input"
class="rounded-xl border border-border/70 bg-surface-secondary px-4 py-2 text-sm shadow-sm focus-visible:border-accent"
placeholder="New web app"
/>
</div>
);
}Customizing the component classes
The base class .input powers every instance. Override it once with @layer components.
@layer components {
.input {
@apply rounded-lg border border-border px-4 py-2 text-sm shadow-sm transition-colors;
&:hover {
@apply bg-surface-secondary border-border/80;
}
&:focus-visible {
@apply border-accent ring-2 ring-accent/20;
}
&[data-invalid] {
@apply border-danger text-danger;
}
}
}CSS Classes
.input– Native input element styling.input--primary/.input--secondary– Visual variants.input--full-width– Full width modifier
Interactive States
- Hover:
:hover - Focus:
:focus - Invalid:
[data-invalid](stamped by the enclosing TextField; also syncs witharia-invalid) - Disabled:
:disabled
API Reference
Input Props
Input accepts all standard HTML <input> attributes plus the following:
| Prop | Type | Default | Description |
|---|---|---|---|
class | string | - | Tailwind classes merged with the component styles. |
fullWidth | boolean | false | Whether the input should take full width of its container |
variant | "primary" | "secondary" | "primary" | Visual variant of the component. primary is the default style with shadow. secondary is a lower emphasis variant without shadow, suitable for use in surfaces. |
For validation props like
isInvalidandisRequired, use TextField with Input as a child component.
Differences from HeroUI React
- Use
classinstead ofclassNameandforinstead ofhtmlForon labels. - Control standalone inputs with
onInput(per keystroke); Solid'sonChangefires on blur. Inside a TextField, use the field'sonChange(value)instead. - Inside a TextField the input is wired through Kobalte, which stamps
data-invalidas an attribute (no="true"value) — both selector forms are styled.
Last updated: 7/19/26, 3:27 AM