YaVendio Registry
Components

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-input
npx shadcn@latest add @yavendio/ya-input
yarn dlx shadcn@latest add @yavendio/ya-input
import { 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:

TypeDescriptionUsage
textStandard text inputGeneral text entry, emails, passwords
fileFile selection with buttonDocument uploads, image uploads
tagTag/chip input for multiple valuesCategories, 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.

No file selected

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.

designui

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.

SizeHeightUsage
md40pxMost use cases, default
sm32pxCompact 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

OrientationDescriptionFeatures
verticalLabel above inputHelp text below, counter right of label
horizontalLabel 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.

0/100

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

No file selected
<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

No file selected

File size exceeds 5MB limit

invalid-tag

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

No file selected

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

3/10
reacttypescriptnextjs

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

No file selected

Upload a profile picture (optional)

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

PropTypeDefaultDescription
inputType'text' | 'file' | 'tag''text'The type of input to render
size'md' | 'sm''md'Input field size
orientation'vertical' | 'horizontal''vertical'Layout orientation
labelstring-Label text
helpTextstring-Help text (vertical only)
errorTextstring-Error message (vertical only, when destructive)
placeholderstring-Placeholder text
counter{ current: number; max: number }-Character counter
iconLeadingReactNode-Icon at the start of input
buttonReactNode-External button
destructivebooleanfalseApplies error styling
disabledbooleanfalseDisable the input
classNamestring-Additional classes

File Input Props

PropTypeDefaultDescription
fileTextstring'Choose file'Text for the file button
acceptstring-Accepted file types
onFileSelect(file: File | null) => void-File selection callback

Tag Input Props

PropTypeDefaultDescription
tagsstring[][]Array of current tags
onTagsChange(tags: string[]) => void-Tags change callback

Extends all standard <input> HTML attributes.

Accessibility

Best Practices

DoDon't
Use appropriate input typesUse text for file uploads
Always include a labelSkip labels for accessibility
Use help text to guide usersLeave users guessing
Display clear error messagesVague error feedback
Use destructive for validationRed styling without prop
Use horizontal orientation sparinglyForce 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']

On this page