---
title: 'Form.Control'
type: 'component'
components:
- FormControl
categories:
- Forms
status: 'Stable'
designStatus: 'Done'
devStatus: 'Done'
notes: |

---

A form control renders a space for user input (`input` or `select`). It can be
decorated with leading or trailing elements, and have a floating label.

Prefer to use the Form.Control component inside a `Form.Group`. The `Form.Group`
provides a context for the control to ensure accessibility requirements for
labels and descriptions are met.

Note: extra props added to this component are passed as attributes to the
underlying DOM node (`input` by default). See MDN for documentation on available
[input attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes)
or [select attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attributes).

## Usage with decorators and floating label

```jsx live
() => {
  const [value, setValue] = useState('');
  return (
    <Form.Group>
      <Form.Control
        leadingElement={<Icon src={FavoriteBorder} />}
        trailingElement={<Icon src={Verified} />}
        floatingLabel="What kind of cats?"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
    </Form.Group>
  );
}
```

## Input types

```jsx live
() => {
  {/* start example state */}
  const [type, setType] = useState('default');
  const [value, setValue] = useState('');
  {/* end example state */}
  const handleChange = (e) => setValue(e.target.value);

  const inputs = {
    default: (
      <>
        <h3>Default</h3>
        <Form.Group>
          <Form.Control
            value={value}
            onChange={handleChange}
            leadingElement={<Icon src={FavoriteBorder} />}
            floatingLabel="What kind of cats?"
          />
        </Form.Group>
      </>
    ),
    textarea: (<>
      <h3>Textarea</h3>
      <Form.Group>
        <Form.Control
          as="textarea"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="What kind of cats?"
        />
      </Form.Group>
    </>),
    select: (<>
      <h3>Select</h3>
      <Form.Group>
        <Form.Control
          as="select"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="What kind of cats?"
        >
          <option value="">Select a cat</option>
          <option>Persian cat</option>
          <option>British Shorthair</option>
          <option>Maine Coon</option>
          <option>Siamese cat</option>
        </Form.Control>
      </Form.Group>
    </>),
    password: (<>
      <h3>Password</h3>
      <Form.Group>
        <Form.Control
          type="password"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="Password cats?"
        />
      </Form.Group>
    </>),
    date: (<>
      <h3>Date picker</h3>
      <Form.Group>
        <Form.Control
          type="date"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="When cats?"
        />
      </Form.Group>
    </>),
    number: (<>
      <h3>Number</h3>
      <Form.Group>
        <Form.Control
          type="number"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="How many cats?"
        />
      </Form.Group>
    </>),
    time: (<>
      <h3>Time picker</h3>
      <Form.Group>
        <Form.Control
          type="time"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="Time cats?"
        />
      </Form.Group>
    </>),
  };
  return (
    <>
      {/* start example form block */}
      <ExamplePropsForm
        inputs={[
          { value: type, setValue: setType, options: Object.keys(inputs), name: 'Input type' },
        ]}
      />
      {/* end example form block */}
      
      {inputs[type]}
    </>
  );
}
```

## Input masks
Paragon uses the [react-imask](https://www.npmjs.com/package/react-imask) library,
which allows you to add masks of different types for inputs.
To create your own mask, you need to pass the required mask pattern (`+{1} (000) 000-0000`) to the `inputMask` property. <br />
See [react-imask](https://imask.js.org) for documentation on available props.

```jsx live
() => {
  {/* start example state */}
  const [maskType, setMaskType] = useState('phone');
  const [value, setValue] = useState('');
  {/* end example state */}
  const handleChange = (e) => setValue(e.target.value);

  const inputsWithMask = {
    phone: (
      <>
        <h3>Phone</h3>
        <Form.Group>
          <Form.Control
            inputMask="+{1} (000) 000-0000"
            value={value}
            onChange={handleChange}
            leadingElement={<Icon src={FavoriteBorder} />}
            floatingLabel="What is your phone number?"
          />
        </Form.Group>
      </>
    ),
    creditCard: (<>
      <h3>Credit card</h3>
      <Form.Group>
        <Form.Control
          inputMask="0000 0000 0000 0000"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="What is your credit card number?"
        />
      </Form.Group>
    </>),
    securePassword: (<>
      <h3>Secure password</h3>
      <Form.Group>
        <Form.Control
          inputMask="XXX-XX-0000"
          value={value}
          definitions={{
            X: {
              mask: '0',
              displayChar: 'X',
              placeholderChar: '#',
            },
          }}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="What is your password?"
        />
      </Form.Group>
    </>),
    OTPpassword: (<>
      <h3>OTP password</h3>
      <Form.Group>
        <Form.Control
          inputMask="G-00000"
          value={value}
          onChange={handleChange}
          leadingElement={<Icon src={FavoriteBorder} />}
          floatingLabel="What is your OPT password?"
        />
      </Form.Group>
    </>),
    price: (
        <>
          <h3>Course priсe</h3>
          <Form.Group>
            <Form.Control
              inputMask="$num"
              blocks={{
                num: {
                  // nested masks are available!
                  mask: Number,
                  thousandsSeparator: ' '
                }
              }}
              value={value}
              onChange={handleChange}
              leadingElement={<Icon src={FavoriteBorder} />}
              floatingLabel="What is the price of this course?"
            />
          </Form.Group>
        </>
    ),
  };

  return (
    <>
      {/* start example form block */}
      <ExamplePropsForm
        inputs={[
          { value: maskType, setValue: setMaskType, options: Object.keys(inputsWithMask), name: 'Mask variants' },
        ]}
      />
      {/* end example form block */}

      {inputsWithMask[maskType]}
    </>
  );
}
```

## Input masks with clear value
To get a value without a mask, you need to use `onChange` instead of `onAccept` to handle changes.

```jsx live
() => {
  const [value, setValue] = useState('');

  return (
      <>
        <Form.Group>
          <Form.Control
            inputMask="+{1} (000) 000-0000"
            leadingElement={<Icon src={FavoriteBorder} />}
            trailingElement={<Icon src={Verified} />}
            floatingLabel="What is your phone number?"
            value={value}
            // depending on prop above first argument is
            // `value` if `unmask=false`,
            // `unmaskedValue` if `unmask=true`,
            // `typedValue` if `unmask='typed'`
            onAccept={(_, mask) => setValue(mask._unmaskedValue)}
          />
        </Form.Group>
        Unmasked value: {JSON.stringify(value)}
      </>
  );
}
```

## Textarea autoResize

`autoResize` prop allows input to be resized according to the content height.

```jsx live
<Form.Control
  as="textarea"
  autoResize
  floatingLabel="Write something long"
/>
```

## Validation

```jsx live
() => {
  const [value, setValue] = useState('');
  const handleChange = (e) => setValue(e.target.value);
  return (
    <>
      <Form.Group>
        <FormLabel>What kind of cats?</FormLabel>
        <Form.Control value={value} onChange={handleChange} />
      </Form.Group>

      <Form.Group isInvalid>
        <FormLabel>What kind of cats?</FormLabel>
        <Form.Control value={value} onChange={handleChange} />
      </Form.Group>

      <Form.Group isValid>
        <FormLabel>What kind of cats?</FormLabel>
        <Form.Control value={value} onChange={handleChange} />
      </Form.Group>
    </>
  );
}
```

## Sizes

```jsx live
() => {
  const [value, setValue] = useState('');
  return (
    <>
      <Form.Group size="sm">
        <Form.Control
          leadingElement={<Icon src={FavoriteBorder} />}
          trailingElement={<Icon src={Verified} />}
          floatingLabel="What kind of cats?"
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      </Form.Group>
      <Form.Group>
        <Form.Control
          leadingElement={<Icon src={FavoriteBorder} />}
          trailingElement={<Icon src={Verified} />}
          floatingLabel="What kind of cats?"
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      </Form.Group>
      <Form.Group size="lg">
        <Form.Control
          leadingElement={<Icon src={FavoriteBorder} />}
          trailingElement={<Icon src={Verified} />}
          floatingLabel="What kind of cats?"
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      </Form.Group>
    </>
  );
}
```
