Skip to main content

Input Components

Proton provides a comprehensive set of input components for forms and data entry, including text inputs, checkboxes, radio buttons, and specialized inputs.

Input

The base text input component. Location: components/input/Input.tsx
This component is deprecated. Consider using Input from @proton/atoms or InputFieldTwo for new code.

Basic Usage

import Input from '@proton/components/components/input/Input';
import { useState } from 'react';

const MyForm = () => {
  const [value, setValue] = useState('');

  return (
    <Input
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Enter text"
    />
  );
};

Props

Extends InputHTMLAttributes<HTMLInputElement>
value
string
required
The input value
onChange
(e: ChangeEvent) => void
required
Change event handler
placeholder
string
Placeholder text
error
string
Error message to display below the input
icon
ReactElement
Icon element to display on the right side
loading
boolean
Shows loading state and disables input. Default: false
fullWidth
boolean
Makes input take full width. Default: true
disabled
boolean
Disables the input
required
boolean
Marks field as required. Default: false
onPressEnter
KeyboardEventHandler
Handler called when Enter key is pressed

Examples

<Input
  value={value}
  onChange={(e) => setValue(e.target.value)}
  placeholder="Enter your name"
/>

SearchInput

Specialized input for search functionality with built-in magnifier icon. Location: components/input/SearchInput.tsx

Usage

import SearchInput from '@proton/components/components/input/SearchInput';

const MySearch = () => {
  const [query, setQuery] = useState('');

  return (
    <SearchInput
      value={query}
      onChange={(e) => setQuery(e.target.value)}
      placeholder="Search..."
    />
  );
};

PasswordInput

Input with show/hide password toggle. Location: components/input/PasswordInput.tsx
This component is deprecated. Use PasswordInputTwo instead.

Usage

import PasswordInput from '@proton/components/components/input/PasswordInput';

const MyLoginForm = () => {
  const [password, setPassword] = useState('');

  return (
    <PasswordInput
      value={password}
      onChange={(e) => setPassword(e.target.value)}
      placeholder="Password"
    />
  );
};

Checkbox

Checkbox input with label support. Location: components/input/Checkbox.tsx

Usage

import Checkbox from '@proton/components/components/input/Checkbox';

const MyForm = () => {
  const [agreed, setAgreed] = useState(false);

  return (
    <Checkbox
      checked={agreed}
      onChange={(e) => setAgreed(e.target.checked)}
    >
      I agree to the terms and conditions
    </Checkbox>
  );
};

Props

checked
boolean
Whether checkbox is checked
onChange
(e: ChangeEvent) => void
Change event handler
indeterminate
boolean
Display a third state [–]. Default: false
loading
boolean
Shows loading state. Interactions blocked. Default: false
disabled
boolean
Disables the checkbox
backgroundColor
string
Custom background color (CSS color value)
borderColor
string
Custom border color (CSS color value)
color
string
Custom checkmark color (CSS color value)
gap
string
Gap between checkbox and label. Default: gap-2

Examples

<Checkbox checked={isChecked} onChange={handleChange}>
  Enable notifications
</Checkbox>

Radio & RadioGroup

Radio button inputs with group management. Location: components/input/Radio.tsx, components/input/RadioGroup.tsx

Usage

import Radio from '@proton/components/components/input/Radio';
import RadioGroup from '@proton/components/components/input/RadioGroup';

const MyForm = () => {
  const [selected, setSelected] = useState('option1');

  return (
    <RadioGroup
      name="my-options"
      value={selected}
      onChange={setSelected}
      options={[
        { value: 'option1', label: 'Option 1' },
        { value: 'option2', label: 'Option 2' },
        { value: 'option3', label: 'Option 3' },
      ]}
    />
  );
};

TextArea

Multi-line text input. Location: components/input/TextArea.tsx

Usage

import TextArea from '@proton/components/components/input/TextArea';

const MyForm = () => {
  const [message, setMessage] = useState('');

  return (
    <TextArea
      value={message}
      onChange={(e) => setMessage(e.target.value)}
      placeholder="Enter your message"
      rows={5}
    />
  );
};

DateInput

Date picker input component. Location: components/input/DateInput.tsx

Usage

import DateInput from '@proton/components/components/input/DateInput';

const MyForm = () => {
  const [date, setDate] = useState<Date>(new Date());

  return (
    <DateInput
      value={date}
      onChange={setDate}
      placeholder="Select date"
    />
  );
};

TimeInput

Time picker input component. Location: components/input/TimeInput.tsx

Usage

import TimeInput from '@proton/components/components/input/TimeInput';

const MyForm = () => {
  const [time, setTime] = useState('12:00');

  return (
    <TimeInput
      value={time}
      onChange={setTime}
      placeholder="Select time"
    />
  );
};

EmailInput

Email input with validation. Location: components/input/EmailInput.tsx

Usage

import EmailInput from '@proton/components/components/input/EmailInput';

const MyForm = () => {
  const [email, setEmail] = useState('');

  return (
    <EmailInput
      value={email}
      onChange={(e) => setEmail(e.target.value)}
      placeholder="[email protected]"
    />
  );
};

IntegerInput

Numeric input restricted to integers. Location: components/input/IntegerInput.tsx

Usage

import IntegerInput from '@proton/components/components/input/IntegerInput';

const MyForm = () => {
  const [count, setCount] = useState(0);

  return (
    <IntegerInput
      value={count}
      onChange={setCount}
      min={0}
      max={100}
    />
  );
};

FileInput

File upload input component. Location: components/input/FileInput.tsx

Usage

import FileInput from '@proton/components/components/input/FileInput';

const MyUpload = () => {
  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    console.log('Selected files:', files);
  };

  return (
    <FileInput
      onChange={handleFileChange}
      accept="image/*"
      multiple
    >
      Choose files
    </FileInput>
  );
};

Best Practices

Form Validation

const [email, setEmail] = useState('');
const [error, setError] = useState('');

const validateEmail = (value: string) => {
  if (!value) {
    setError('Email is required');
  } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
    setError('Invalid email format');
  } else {
    setError('');
  }
};

<Input
  type="email"
  value={email}
  onChange={(e) => {
    setEmail(e.target.value);
    validateEmail(e.target.value);
  }}
  error={error}
  required
/>

Accessibility

// Provide proper labels
<label htmlFor="username">Username</label>
<Input
  id="username"
  value={username}
  onChange={(e) => setUsername(e.target.value)}
  aria-describedby="username-help"
/>
<span id="username-help" className="text-sm color-weak">
  Choose a unique username
</span>

Controlled Components

Always use controlled components with state:
const [value, setValue] = useState('');

<Input
  value={value}
  onChange={(e) => setValue(e.target.value)}
/>

Source Code

View source:
  • Input: packages/components/components/input/Input.tsx:1
  • Checkbox: packages/components/components/input/Checkbox.tsx:1
  • PasswordInput: packages/components/components/input/PasswordInput.tsx:1

Build docs developers (and LLMs) love