Text Input

Sizes

Three sizes to fit different contexts and information hierarchy.

<input type="text" class="input input-sm" placeholder="Small">
<input type="text" class="input input-md" placeholder="Medium">
<input type="text" class="input input-lg" placeholder="Large">

States

Visual feedback for different interaction states.

Enter a valid email
Looks good!
<!-- Error state -->
<input type="text" class="input input-error" value="invalid">
<span class="input-hint input-hint-error">Enter a valid email</span>

<!-- Success state -->
<input type="text" class="input input-success" value="valid">
<span class="input-hint input-hint-success">Looks good!</span>

With Icons

Icons provide visual context and improve scannability.

<div class="input-with-icon">
  <svg class="input-icon input-icon-left">...</svg>
  <input type="text" class="input has-icon-left" placeholder="Search...">
</div>

Textarea

Basic Textarea

Multi-line text input for longer content.

Keep it short and sweet
<textarea class="textarea" rows="4" placeholder="What's on your mind?"></textarea>

Auto-resize

Textarea that grows with content for a seamless writing experience.

<textarea class="textarea textarea-auto" rows="2"></textarea>

<script>
textarea.addEventListener('input', function() {
  this.style.height = 'auto';
  this.style.height = this.scrollHeight + 'px';
});
</script>

Select

Basic Select

Dropdown selection for choosing from predefined options.

<div class="select-wrapper">
  <select class="select">
    <option value="">Choose a persona...</option>
    <option value="ferni">Ferni</option>
    <option value="maya">Maya</option>
  </select>
  <svg class="select-icon">...</svg>
</div>

Checkbox & Radio

Checkboxes

Multiple selections with clear visual feedback.

<label class="checkbox-wrapper">
  <input type="checkbox" class="checkbox" checked>
  <span class="checkbox-control"></span>
  <span class="checkbox-label">Enable notifications</span>
</label>

Radio Buttons

Single selection from a group of options.

<label class="radio-wrapper">
  <input type="radio" name="theme" class="radio" checked>
  <span class="radio-control"></span>
  <span class="radio-label">Light theme</span>
</label>

Toggle Switch

Basic Toggle

On/off controls for binary settings.

<label class="toggle-wrapper">
  <input type="checkbox" class="toggle-input" checked>
  <span class="toggle-control"></span>
  <span class="toggle-label">Voice responses</span>
</label>

CSS Implementation

/* Base Input */
.input {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  transition: all var(--duration-fast) var(--ease-ease-out);
}

.input:focus {
  outline: none;
  border-color: var(--accent-primary);
  box-shadow: 0 0 0 3px var(--accent-subtle);
}

.input::placeholder {
  color: var(--text-muted);
}

/* Sizes */
.input-sm { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.input-md { padding: var(--space-3) var(--space-4); }
.input-lg { padding: var(--space-4) var(--space-5); font-size: var(--text-base); }

/* States */
.input-error {
  border-color: var(--error);
}

.input-error:focus {
  box-shadow: 0 0 0 3px rgba(var(--error-rgb), 0.15);
}

.input-success {
  border-color: var(--success);
}

.input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--bg-secondary);
}

/* Hints */
.input-hint {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: var(--space-1);
}

.input-hint-error { color: var(--error); }
.input-hint-success { color: var(--success); }

/* Checkbox */
.checkbox-wrapper {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
}

.checkbox {
  position: absolute;
  opacity: 0;
}

.checkbox-control {
  width: 20px;
  height: 20px;
  border: 2px solid var(--border-medium);
  border-radius: var(--radius-sm);
  transition: all var(--duration-fast) var(--ease-ease-out);
  position: relative;
}

.checkbox:checked + .checkbox-control {
  background: var(--accent-primary);
  border-color: var(--accent-primary);
}

.checkbox:checked + .checkbox-control::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Toggle */
.toggle-control {
  width: 44px;
  height: 24px;
  background: var(--bg-tertiary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-full);
  position: relative;
  transition: all var(--duration-fast) var(--ease-ease-out);
}

.toggle-control::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: white;
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: transform var(--duration-fast) var(--ease-spring);
}

.toggle-input:checked + .toggle-control {
  background: var(--accent-primary);
  border-color: var(--accent-primary);
}

.toggle-input:checked + .toggle-control::after {
  transform: translateX(20px);
}

Accessibility

Labels Required

Every input must have an associated <label> for screen readers. Never use placeholder as the only label.

Focus Indicators

Clear focus states with sufficient contrast. The accent ring provides 3:1 contrast against backgrounds.

Error Messaging

Errors use aria-describedby to connect inputs to their error messages for screen readers.

Keyboard Navigation

All inputs are keyboard accessible. Checkboxes and radios respond to Space, selects to Arrow keys.