# Text Input
> Text inputs enable the user to interact with and input content and data.

## Import

```js
import { TextInput } from '@gemini-suite/vera-react';
```

## Examples

### Basic

```jsx
<TextInput aria-label="Input label" placeholder="Basic, standalone usage" />
```

### Controlled

It is most common to set up `TextInput` as a [controlled component](https://reactjs.org/docs/forms.html#controlled-components), meaning that React state drives its value. To achieve this you must provide `value` and `onChange` properties.

```jsx
() => {
  const [value, setValue] = React.useState('');
  const handleChange = event => setValue(event.target.value);

  return (
    <Flex flow="column" gap="spacingS">
      <Box>Value: {value}</Box>
      <TextInput
        value={value}
        onChange={handleChange}
        aria-label="Input label"
        placeholder="Sample placeholder"
      />
    </Flex>
  );
};
```

### With Form Field

`TextInput` should be clearly labeled so it's obvious to users what they should enter. Optionally, you may want to connect helper text and/or validation feedback message to the input element.
Thus it is recommended to wrap inputs with [Form Field](/components/forms/form-field) to create a consistent set of form fields that are accessible to screen reader users.

```jsx
<Flex flow="column" gap="spacingM">
  <FormField.Root as={Flex} flow="column">
    <FormField.Label>{'Name'}</FormField.Label>
    <TextInput />
    <FormField.HelperText>{'Hint: your first name.'}</FormField.HelperText>
  </FormField.Root>
  <FormField.Root as={Flex} flow="column" validationStatus="error" isRequired>
    <FormField.Label>{'Name'}</FormField.Label>
    <TextInput />
    <FormField.FeedbackMessage>
      <FormField.FeedbackIcon />
      {'Name is required.'}
    </FormField.FeedbackMessage>
  </FormField.Root>
</Flex>
```

### Placeholder

Placeholder text provides examples of what to enter.

<Callout variant="important">

Placeholder text disappears after the user begins entering data into the input and should not contain crucial information. Do not use placeholder text as a replacement for labels or descriptions.

</Callout>

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label>{'Address line 1'}</FormField.Label>
  <TextInput placeholder="e.g. Eckersbergs gate 20" />
</FormField.Root>
```

### Disabled input

Pass `isDisabled` prop to the accompanying `FormField` and it will cascade down to the input.

```jsx
<FormField.Root as={Flex} flow="column" isDisabled>
  <FormField.Label>{'Name'}</FormField.Label>
  <TextInput />
</FormField.Root>
```

You can also pass `isDisabled` prop directly to `TextInput`.

```jsx
<TextInput aria-label="Input label" isDisabled />
```

### With leading/trailing visuals

In some scenarios, you might need to add a visual positioned on the edge inside the input.
This includes icons for decoration and help distinguishing between inputs, as well as special form of help text that works best inline.
`leadingVisual` and `trailingVisual` props help with this use case.

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label>{'Search'}</FormField.Label>
  <TextInput leadingVisual={<SvgIcon iconName="search" />} />
</FormField.Root>
```

Use `leadingVisual` for things like currency symbols, country codes, etc.:

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label>{'Price'}</FormField.Label>
  <TextInput
    type="number"
    leadingVisual="€"
    defaultValue="2.00"
    autoComplete="off"
  />
</FormField.Root>
```

Use `trailingVisual` for things like units of measure:

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label>{'Length'}</FormField.Label>
  <TextInput
    className="maw5ch"
    type="number"
    trailingVisual="cm"
    defaultValue="25"
    autoComplete="off"
  />
</FormField.Root>
```

By using `<Button>` as `trailingVisual`, you can create a password input with a show/hide password functionality.

```jsx
() => {
  const [show, setShow] = React.useState(false);
  const handleClick = () => setShow(show => !show);

  return (
    <FormField.Root as={Flex} flow="column">
      <FormField.Label>{'Password'}</FormField.Label>
      <TextInput
        type={show ? 'text' : 'password'}
        autoComplete="off"
        placeholder="Enter password"
        trailingVisual={
          <Tooltip content={show ? 'Hide' : 'Show'}>
            <Button
              withLoneIcon
              size="xSmall"
              variant="ghost"
              onClick={handleClick}
            >
              <SvgIcon iconName={show ? 'hide' : 'show'} />
            </Button>
          </Tooltip>
        }
      />
    </FormField.Root>
  );
};
```

### Sizes

Vera provides two `TextInput` sizes ‐ `medium` and `small`, with the `medium` size used by default. All sizes are aligned with sizes of other related components like [Button](/components/button) or [Select](/components/forms/select).

```jsx
<Flex flow="column">
  <TextInput
    size="small"
    leadingVisual={<SvgIcon iconName="mail" />}
    placeholder="Example input"
  />
  <TextInput
    size="medium"
    leadingVisual={<SvgIcon iconName="mail" />}
    placeholder="Example input"
  />
</Flex>
```

#### Size inheritance

`TextInput` automatically inherits size, when placed inside a [FormField component](/components/forms/form-field).

```jsx
<Flex flow="column">
  <FormField.Root as={Flex} flow="column" size="small">
    <FormField.Label>{'Small'}</FormField.Label>
    <TextInput
      leadingVisual={<SvgIcon iconName="mail" />}
      placeholder="Example input"
    />
  </FormField.Root>
  <FormField.Root as={Flex} flow="column">
    <FormField.Label>{'Medium'}</FormField.Label>
    <TextInput
      leadingVisual={<SvgIcon iconName="mail" />}
      placeholder="Example input"
    />
  </FormField.Root>
</Flex>
```

#### Responsive

`TextInput` supports responsive syntax for its `size` property, which means you can change its size based on the viewport.

```jsx
<TextInput
  aria-label="Input label"
  size={{ '@initial': 'medium', '@mqLargeAndUp': 'small' }}
  leadingVisual={<SvgIcon iconName="mail" />}
  placeholder="Example input"
/>
```

#### Multi-sizing

Vera provides `applySizes` utility, which lets you specify size "scopes" within your app.
All inputs within a scope will share the same size unless overwritten on a per-control basis.

```jsx
<Flex
  gap="spacingS"
  className={applySizes({
    control: 'small'
  })}
  flow="column"
>
  <TextInput
    aria-label="Input label"
    leadingVisual={<SvgIcon iconName="mail" />}
    placeholder="Example input"
  />
  <TextInput
    aria-label="Input label"
    leadingVisual={<SvgIcon iconName="mail" />}
    placeholder="Example input"
  />
</Flex>
```

### Input groups

Visually grouping closely related fields such as first and last name, or city and zip code can help users make sense of the information they must fill in.
You can use layout component such as [Auto Grid](/components/layout/auto-grid) to arrange fields into groups, or to vary field layouts across different screen sizes.

<Callout variant="tip">

Fields that are not directly related to each other should not be visually
grouped together as this can make it easier to overlook certain fields.

</Callout>

```jsx
<ContentBlock max="containerNarrow" gutters="none" center={false}>
  <Flex flow="column" gap="spacingM">
    <AutoGrid min="20ch">
      <FormField.Root as={Flex} flow="column">
        <FormField.Label>{'First name'}</FormField.Label>
        <TextInput />
      </FormField.Root>
      <FormField.Root as={Flex} flow="column">
        <FormField.Label>{'Last name'}</FormField.Label>
        <TextInput />
      </FormField.Root>
    </AutoGrid>
    <FormField.Root as={Flex} flow="column">
      <FormField.Label>{'Email'}</FormField.Label>
      <TextInput placeholder="e.g. person@invera-tech.com" />
    </FormField.Root>
  </Flex>
</ContentBlock>
```

---

## API Reference

<Callout variant="tip">

In addition to the props below, you can pass all `React.InputHTMLAttributes`.

</Callout>

| Name               | Type                                                                        | Default  | Description                                                                                                                                                                                                                                  | Required |
| ------------------ | --------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`              | `StitchesCss`                                                               |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants. |          |
| `inputCss`         | `StitchesCss`                                                               |          | Override the input styles in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants.            |          |
| `type`             | `"number" \| "text" \| "tel" \| "url" \| "email" \| "search" \| "password"` | `"text"` | The type of the input.                                                                                                                                                                                                                       |          |
| `isDisabled`       | `boolean`                                                                   |          | When `true`, the input will be disabled, preventing the user from interacting with it.                                                                                                                                                       |          |
| `isReadOnly`       | `boolean`                                                                   |          | When `true`, the input will be readonly, which means its value cannot be edited but it can still be selected and copied.                                                                                                                     |          |
| `isRequired`       | `boolean`                                                                   |          | When `true`, the input will be required.                                                                                                                                                                                                     |          |
| `validationStatus` | `"error" \| "success" \| "warning"`                                         |          | Styles the input to match the status.                                                                                                                                                                                                        |          |
| `leadingVisual`    | `React.ReactNode`                                                           |          | Visual positioned on the left edge inside the input.                                                                                                                                                                                         |          |
| `trailingVisual`   | `React.ReactNode`                                                           |          | Visual positioned on the right edge inside the input.                                                                                                                                                                                        |          |
| `size`             | `"medium" \| "small"`                                                       |          | The size of the input.                                                                                                                                                                                                                       |          |
