apps/eclipse/content/design-system/components/input.mdx
import { Input, inputVariants, Button, Field, FieldLabel, FieldDescription, FieldError } from "@prisma/eclipse";
Basic Input
import { Input } from "@prisma/eclipse";
export function MyComponent() {
return <Input placeholder="Enter text..." />;
}
Live Example:
<div className="max-w-md my-4"> <Input placeholder="Enter text..." /> </div>Input Types
The Input component supports all native HTML input types:
import { Input } from "@prisma/eclipse";
export function InputTypes() {
return (
<div className="space-y-4 max-w-md">
<Input type="text" placeholder="Text input" />
<Input type="email" placeholder="[email protected]" />
<Input type="password" placeholder="Password" />
<Input type="number" placeholder="123" />
<Input type="tel" placeholder="(555) 555-5555" />
<Input type="url" placeholder="https://example.com" />
<Input type="search" placeholder="Search..." />
<Input type="date" />
</div>
);
}
Live Example:
<div className="space-y-4 max-w-md my-4"> <Input type="text" placeholder="Text input" /> <Input type="email" placeholder="[email protected]" /> <Input type="password" placeholder="Password" /> <Input type="number" placeholder="123" /> <Input type="tel" placeholder="(555) 555-5555" /> <Input type="url" placeholder="https://example.com" /> <Input type="search" placeholder="Search..." /> <Input type="date" /> </div>Input Sizes
import { Input } from "@prisma/eclipse";
export function InputSizes() {
return (
<div className="space-y-4 max-w-md">
<Input size="lg" placeholder="Large (default)" />
<Input size="xl" placeholder="Extra Large" />
<Input size="2xl" placeholder="2X Large" />
</div>
);
}
Live Example:
<div className="space-y-4 max-w-md my-4"> <Input size="lg" placeholder="Large (default)" /> <Input size="xl" placeholder="Extra Large" /> <Input size="2xl" placeholder="2X Large" /> </div>With Field Component
Use the Field component for proper form structure with labels and descriptions:
import { Input, Field, FieldLabel, FieldDescription } from "@prisma/eclipse";
export function InputWithField() {
return (
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<Input id="username" placeholder="Enter your username" />
<FieldDescription>Choose a unique username for your account.</FieldDescription>
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="username-field">Username</FieldLabel> <Input id="username-field" placeholder="Enter your username" /> <FieldDescription>Choose a unique username for your account.</FieldDescription> </Field> </div>Disabled State
import { Input } from "@prisma/eclipse";
export function DisabledInput() {
return (
<div className="space-y-4 max-w-md">
<Input placeholder="Disabled input" disabled />
<Input defaultValue="Disabled with value" disabled />
</div>
);
}
Live Example:
<div className="space-y-4 max-w-md my-4"> <Input placeholder="Disabled input" disabled /> <Input defaultValue="Disabled with value" disabled /> </div>Invalid State with Field
Use the Field component with FieldError for proper error handling:
import { Input, Field, FieldLabel, FieldDescription, FieldError } from "@prisma/eclipse";
export function InvalidInputWithField() {
return (
<Field>
<FieldLabel htmlFor="email-invalid">Email</FieldLabel>
<Input
id="email-invalid"
type="email"
defaultValue="invalid-email"
aria-invalid="true"
/>
<FieldDescription>We'll send updates to this address.</FieldDescription>
<FieldError>Please enter a valid email address</FieldError>
</Field>
);
}
Live Example:
<div className="max-w-md my-4"> <Field> <FieldLabel htmlFor="email-invalid-field">Email</FieldLabel> <Input id="email-invalid-field" type="email" defaultValue="invalid-email" aria-invalid="true" /> <FieldDescription>We'll send updates to this address.</FieldDescription> <FieldError>Please enter a valid email address</FieldError> </Field> </div>Invalid State (Basic)
Use the aria-invalid attribute to mark an input as invalid for validation errors:
import { Input } from "@prisma/eclipse";
export function InvalidInput() {
return (
<div className="space-y-4 max-w-md">
<div className="space-y-2">
<label htmlFor="invalid-email" className="text-sm font-medium">
Email
</label>
<Input
id="invalid-email"
type="email"
defaultValue="invalid-email"
aria-invalid="true"
/>
<span className="text-sm text-foreground-error block">
Please enter a valid email address
</span>
</div>
<div className="space-y-2">
<label htmlFor="invalid-password" className="text-sm font-medium">
Password
</label>
<Input
id="invalid-password"
type="password"
defaultValue="123"
aria-invalid="true"
/>
<span className="text-sm text-foreground-error block">
Password must be at least 8 characters
</span>
</div>
</div>
);
}
Live Example:
<div className="space-y-4 max-w-md my-4"> <div className="space-y-2"> <label htmlFor="invalid-email" className="text-sm font-medium"> Email </label> <Input id="invalid-email" type="email" defaultValue="invalid-email" aria-invalid="true" /> <span className="text-sm text-foreground-error"> Please enter a valid email address </span> </div> <div className="space-y-2"> <label htmlFor="invalid-password" className="text-sm font-medium"> Password </label> <Input id="invalid-password" type="password" defaultValue="123" aria-invalid="true" /> <span className="text-sm text-foreground-error"> Password must be at least 8 characters </span> </div> </div>Form Example
import { Input, Button } from "@prisma/eclipse";
export function FormExample() {
return (
<form className="space-y-4 max-w-md">
<div className="space-y-2">
<label htmlFor="name" className="text-sm font-medium">
Name
</label>
<Input id="name" placeholder="John Doe" required />
</div>
<div className="space-y-2">
<label htmlFor="email" className="text-sm font-medium">
Email
</label>
<Input id="email" type="email" placeholder="[email protected]" required />
</div>
<div className="space-y-2">
<label htmlFor="message" className="text-sm font-medium">
Message
</label>
<Input id="message" placeholder="Your message..." />
</div>
<Button type="submit">Submit</Button>
</form>
);
}
Live Example:
<form className="space-y-4 max-w-md my-4"> <div className="space-y-2"> <label htmlFor="name" className="text-sm font-medium"> Name </label> <Input id="name" placeholder="John Doe" required /> </div> <div className="space-y-2"> <label htmlFor="email" className="text-sm font-medium"> Email </label> <Input id="email" type="email" placeholder="[email protected]" required /> </div> <div className="space-y-2"> <label htmlFor="message" className="text-sm font-medium"> Message </label> <Input id="message" placeholder="Your message..." /> </div> <Button type="submit">Submit</Button> </form>File Input
import { Input } from "@prisma/eclipse";
export function FileInput() {
return (
<div className="space-y-2 max-w-md">
<label htmlFor="file" className="text-sm font-medium">
Upload file
</label>
<Input id="file" size="2xl" type="file" />
</div>
);
}
Live Example:
<div className="space-y-2 max-w-md my-4"> <label htmlFor="file" className="text-sm font-medium"> Upload file </label> <Input id="file" size="2xl" type="file" /> </div>Input
The Input component uses class-variance-authority for size variants. It extends all native HTML input attributes and adds:
type - Input type (text, email, password, number, etc.) (string, default: "text")size - Size variant ("lg" | "xl" | "2xl", default: "lg")className - Additional CSS classes (string, optional)disabled - Disable the input (boolean, default: false)placeholder - Placeholder text (string, optional)defaultValue - Default value for uncontrolled inputs (string, optional)value - Value for controlled inputs (string, optional)onChange - Change event handler (function, optional)onFocus - Focus event handler (function, optional)onBlur - Blur event handler (function, optional)aria-invalid - Mark input as invalid for validation errors (boolean, optional)required attribute for required fieldsaria-invalid to mark invalid inputs and provide error messagesThe Input component is perfect for:
The Input component follows accessibility best practices:
<input> elementaria-invalidid and htmlFor attributesaria-invalidThe Input component uses design tokens and can be customized:
border-stroke-neutral with border-stroke-neutral-strong on focusborder-stroke-error when aria-invalid is truebg-background-defaulttext-foreground-neutral with size text-smtext-foreground-error when aria-invalid is truetext-foreground-neutral-weakrounded-square (6px)shadow-box-lowCustomize by passing className props:
<Input className="border-2 border-blue-500 focus:border-blue-700" />