YA Input
A versatile input component with text, file, and tag types for various data entry needs
The YaInput is a flexible input field component in the YaVendio Design System. It supports multiple input types (text, file, tag), two sizes, vertical/horizontal orientations, and integrates seamlessly with icons and external buttons.
Quick Start
pnpm dlx shadcn@latest add @yavendio/ya-inputnpx shadcn@latest add @yavendio/ya-inputyarn dlx shadcn@latest add @yavendio/ya-inputimport { YaInput } from '@/components/ui/ya-input'
export default function Example() {
return <YaInput label="Email" placeholder="Enter your email" />
}Input Types
YaInput supports three input types for different data entry scenarios:
| Type | Description | Usage |
|---|---|---|
text | Standard text input | General text entry, emails, passwords |
file | File selection with button | Document uploads, image uploads |
tag | Tag/chip input for multiple values | Categories, skills, multiple selections |
Text Input
Standard text input for general text entry.
Choose a unique username
<YaInput
inputType="text"
label="Username"
placeholder="Enter username"
helpText="Choose a unique username"
/>Features:
- Standard text input with label
- Placeholder and help text support
- Icon and button integration
File Input
File input with a "Choose file" button and selected file name display.
Accepted: PDF, DOC, DOCX
<YaInput
inputType="file"
label="Document"
fileText="Choose file"
placeholder="No file selected"
accept=".pdf,.doc,.docx"
onFileSelect={(file) => console.log(file)}
/>Features:
- Custom "Choose file" button text
- Displays selected file name
- Accepts file type restrictions
- Hidden native file input with accessible button
Tag Input
Tag/chip input for managing multiple values.
Press Enter to add, Backspace to remove
const [tags, setTags] = useState(['react', 'typescript'])
<YaInput
inputType="tag"
label="Skills"
placeholder="Add a skill..."
tags={tags}
onTagsChange={setTags}
/>Features:
- Add tags with Enter key
- Remove tags with Backspace or click
- Visual chips with remove buttons
- Auto-adjusting height
Sizes
Two sizes for different use cases.
| Size | Height | Usage |
|---|---|---|
md | 40px | Most use cases, default |
sm | 32px | Compact UIs, tables, toolbars |
<YaInput size="md" label="Medium Input" placeholder="Default size" />
<YaInput size="sm" label="Small Input" placeholder="Compact size" />Orientations
Two layout orientations for label positioning.
This is help text
| Orientation | Description | Features |
|---|---|---|
vertical | Label above input | Help text below, counter right of label |
horizontal | Label beside input (85px width) | No help text, compact layout |
<YaInput
orientation="vertical"
label="Vertical Layout"
placeholder="Label above"
helpText="This is help text"
/>
<YaInput
orientation="horizontal"
label="Horizontal"
placeholder="Label on the left"
/>With Icons
Add a leading icon to the input field. Icons are automatically sized based on input size.
import { Search, Mail, User } from 'lucide-react'
<YaInput label="Search" placeholder="Search..." iconLeading={<Search />} />
<YaInput label="Email" placeholder="name@example.com" iconLeading={<Mail />} />
<YaInput label="Username" placeholder="Enter username" iconLeading={<User />} />Works best with Lucide React. The component automatically clones and resizes icon elements.
With Counter
Display a character counter next to the label.
Brief description about yourself
const [value, setValue] = useState('')
const maxLength = 100
<YaInput
label="Bio"
placeholder="Tell us about yourself"
value={value}
onChange={(e) => setValue(e.target.value.slice(0, maxLength))}
counter={{ current: value.length, max: maxLength }}
helpText="Brief description about yourself"
/>With External Button
Integrate with YaButton for combined input-action patterns.
Subscribe to our newsletter
import { YaButton } from '@/components/ui/ya-button'
import { Mail, ArrowRight } from 'lucide-react'
<YaInput
label="Newsletter"
placeholder="Enter your email"
helpText="Subscribe to our newsletter"
iconLeading={<Mail />}
button={
<YaButton variant="primary" rightIcon={<ArrowRight />}>
Subscribe
</YaButton>
}
/>States
All States
This field has an error
Disabled
<YaInput label="Disabled Input" placeholder="This is disabled" disabled />- Reduced opacity (50%)
pointer-events: none- Non-interactive
Destructive
Apply danger styling for validation errors.
Please enter a valid email address
<YaInput
label="Email"
placeholder="name@example.com"
destructive
errorText="Please enter a valid email address"
/>Features:
- Red border
- Red label text
- Error message displayed below (vertical only)
Destructive Examples
Invalid email format
File size exceeds 5MB limit
One or more tags are invalid
<YaInput
inputType="text"
label="Email"
destructive
errorText="Invalid email format"
/>
<YaInput
inputType="file"
label="Document"
destructive
errorText="File size exceeds 5MB limit"
/>
<YaInput
inputType="tag"
label="Categories"
tags={['invalid-tag']}
onTagsChange={() => {}}
destructive
errorText="One or more tags are invalid"
/>Examples
Newsletter Signup
Get the latest news delivered to your inbox
import { useState } from 'react'
import { YaInput } from '@/components/ui/ya-input'
import { YaButton } from '@/components/ui/ya-button'
import { Mail, ArrowRight } from 'lucide-react'
export default function NewsletterSignup() {
const [email, setEmail] = useState('')
return (
<YaInput
label="Stay Updated"
placeholder="your@email.com"
iconLeading={<Mail />}
helpText="Get the latest news delivered to your inbox"
value={email}
onChange={(e) => setEmail(e.target.value)}
button={
<YaButton variant="primary" rightIcon={<ArrowRight />}>
Subscribe
</YaButton>
}
/>
)
}File Upload
Accepted formats: PDF, DOC, DOCX (max 5MB)
import { useState } from 'react'
import { YaInput } from '@/components/ui/ya-input'
export default function FileUpload() {
const [error, setError] = useState('')
const handleFileSelect = (file: File | null) => {
if (file && file.size > 5 * 1024 * 1024) {
setError('File size must be less than 5MB')
} else {
setError('')
}
}
return (
<YaInput
inputType="file"
label="Upload Resume"
accept=".pdf,.doc,.docx"
onFileSelect={handleFileSelect}
destructive={!!error}
errorText={error}
helpText="Accepted formats: PDF, DOC, DOCX (max 5MB)"
/>
)
}Tag Manager
Add up to 10 skills
import { useState } from 'react'
import { YaInput } from '@/components/ui/ya-input'
import { Tag } from 'lucide-react'
export default function TagManager() {
const [tags, setTags] = useState(['react', 'typescript', 'nextjs'])
return (
<YaInput
inputType="tag"
label="Skills"
placeholder="Type and press Enter..."
iconLeading={<Tag />}
tags={tags}
onTagsChange={setTags}
counter={{ current: tags.length, max: 10 }}
helpText="Add up to 10 skills"
/>
)
}Form with Multiple Inputs
import { YaInput } from '@/components/ui/ya-input'
import { YaButton } from '@/components/ui/ya-button'
import { User, Mail } from 'lucide-react'
<form className="flex flex-col gap-4">
<YaInput label="Full Name" placeholder="John Doe" iconLeading={<User />} />
<YaInput label="Email" placeholder="john@example.com" iconLeading={<Mail />} />
<YaInput
inputType="file"
label="Profile Picture"
accept="image/*"
helpText="Upload a profile picture (optional)"
/>
<div className="flex gap-2 mt-4">
<YaButton type="submit" variant="primary">Save</YaButton>
<YaButton type="button" variant="secondary">Cancel</YaButton>
</div>
</form>Props
YaInput
| Prop | Type | Default | Description |
|---|---|---|---|
inputType | 'text' | 'file' | 'tag' | 'text' | The type of input to render |
size | 'md' | 'sm' | 'md' | Input field size |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout orientation |
label | string | - | Label text |
helpText | string | - | Help text (vertical only) |
errorText | string | - | Error message (vertical only, when destructive) |
placeholder | string | - | Placeholder text |
counter | { current: number; max: number } | - | Character counter |
iconLeading | ReactNode | - | Icon at the start of input |
button | ReactNode | - | External button |
destructive | boolean | false | Applies error styling |
disabled | boolean | false | Disable the input |
className | string | - | Additional classes |
File Input Props
| Prop | Type | Default | Description |
|---|---|---|---|
fileText | string | 'Choose file' | Text for the file button |
accept | string | - | Accepted file types |
onFileSelect | (file: File | null) => void | - | File selection callback |
Tag Input Props
| Prop | Type | Default | Description |
|---|---|---|---|
tags | string[] | [] | Array of current tags |
onTagsChange | (tags: string[]) => void | - | Tags change callback |
Extends all standard <input> HTML attributes.
Accessibility
Best Practices
| Do | Don't |
|---|---|
| Use appropriate input types | Use text for file uploads |
| Always include a label | Skip labels for accessibility |
| Use help text to guide users | Leave users guessing |
| Display clear error messages | Vague error feedback |
Use destructive for validation | Red styling without prop |
| Use horizontal orientation sparingly | Force horizontal in forms |
TypeScript
import { type VariantProps } from 'class-variance-authority'
import { yaInputWrapperVariants, yaInputFieldVariants } from '@/components/ui/ya-input'
type InputOrientation = VariantProps<typeof yaInputWrapperVariants>['orientation']
type InputSize = VariantProps<typeof yaInputFieldVariants>['size']